home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / usr / lib / python2.4 / site-packages / impacket / smb.py < prev    next >
Text File  |  2006-05-23  |  91KB  |  2,373 lines

  1. # Copyright (c) 2003-2006 CORE Security Technologies
  2. #
  3. # This software is provided under under a slightly modified version
  4. # of the Apache Software License. See the accompanying LICENSE file
  5. # for more information.
  6. #
  7. # $Id: smb.py,v 1.7 2006/05/23 21:19:25 gera Exp $
  8. #
  9.  
  10. # -*- mode: python; tab-width: 4 -*-
  11. # $Id: smb.py,v 1.7 2006/05/23 21:19:25 gera Exp $
  12. #
  13. # Copyright (C) 2001 Michael Teo <michaelteo@bigfoot.com>
  14. # smb.py - SMB/CIFS library
  15. #
  16. # This software is provided 'as-is', without any express or implied warranty. 
  17. # In no event will the author be held liable for any damages arising from the 
  18. # use of this software.
  19. #
  20. # Permission is granted to anyone to use this software for any purpose, 
  21. # including commercial applications, and to alter it and redistribute it 
  22. # freely, subject to the following restrictions:
  23. #
  24. # 1. The origin of this software must not be misrepresented; you must not 
  25. #    claim that you wrote the original software. If you use this software 
  26. #    in a product, an acknowledgment in the product documentation would be
  27. #    appreciated but is not required.
  28. #
  29. # 2. Altered source versions must be plainly marked as such, and must not be 
  30. #    misrepresented as being the original software.
  31. #
  32. # 3. This notice cannot be removed or altered from any source distribution.
  33. #
  34. # Altered source done by Alberto Solino
  35.  
  36. # Todo:
  37. # [ ] Try [SMB]transport fragmentation using Transact requests
  38. # [ ] Try other methods of doing write (write_raw, transact2, write, write_and_unlock, write_and_close, write_mpx)
  39. # [-] Try replacements for SMB_COM_NT_CREATE_ANDX  (CREATE, T_TRANSACT_CREATE, OPEN_ANDX works
  40. # [x] Fix forceWriteAndx, which needs to send a RecvRequest, because recv() will not send it
  41. # [x] Fix Recv() when using RecvAndx and the answer comes splet in several packets
  42. # [ ] Try [SMB]transport fragmentation with overlaping segments
  43. # [ ] Try [SMB]transport fragmentation with out of order segments
  44. # [x] Do chained AndX requests
  45.  
  46. import os, sys, socket, string, re, select, errno
  47. import nmb
  48. import types
  49. from random import randint
  50. from struct import *
  51.  
  52. import ntlm
  53. from dcerpc import samr
  54. from structure import Structure
  55.  
  56. unicode_support = 0
  57. unicode_convert = 1
  58.  
  59. try:
  60.     from cStringIO import StringIO
  61. except ImportError:
  62.     from StringIO import StringIO
  63.  
  64. from binascii import a2b_hex
  65.  
  66. CVS_REVISION = '$Revision: 1.7 $'
  67.  
  68. # Shared Device Type
  69. SHARED_DISK = 0x00
  70. SHARED_PRINT_QUEUE = 0x01
  71. SHARED_DEVICE = 0x02
  72. SHARED_IPC = 0x03
  73.  
  74. # Extended attributes mask
  75. ATTR_ARCHIVE = 0x020
  76. ATTR_COMPRESSED = 0x800
  77. ATTR_NORMAL = 0x080
  78. ATTR_HIDDEN = 0x002
  79. ATTR_READONLY = 0x001
  80. ATTR_TEMPORARY = 0x100
  81. ATTR_DIRECTORY = 0x010
  82. ATTR_SYSTEM = 0x004
  83.  
  84. # Service Type
  85. SERVICE_DISK = 'A:'
  86. SERVICE_PRINTER = 'LPT1:'
  87. SERVICE_IPC = 'IPC'
  88. SERVICE_COMM = 'COMM'
  89. SERVICE_ANY = '?????'
  90.  
  91. # Server Type (Can be used to mask with SMBMachine.get_type() or SMBDomain.get_type())
  92. SV_TYPE_WORKSTATION = 0x00000001
  93. SV_TYPE_SERVER      = 0x00000002
  94. SV_TYPE_SQLSERVER   = 0x00000004
  95. SV_TYPE_DOMAIN_CTRL = 0x00000008
  96. SV_TYPE_DOMAIN_BAKCTRL = 0x00000010
  97. SV_TYPE_TIME_SOURCE    = 0x00000020
  98. SV_TYPE_AFP            = 0x00000040
  99. SV_TYPE_NOVELL         = 0x00000080
  100. SV_TYPE_DOMAIN_MEMBER = 0x00000100
  101. SV_TYPE_PRINTQ_SERVER = 0x00000200
  102. SV_TYPE_DIALIN_SERVER = 0x00000400
  103. SV_TYPE_XENIX_SERVER  = 0x00000800
  104. SV_TYPE_NT        = 0x00001000
  105. SV_TYPE_WFW       = 0x00002000
  106. SV_TYPE_SERVER_NT = 0x00004000
  107. SV_TYPE_POTENTIAL_BROWSER = 0x00010000
  108. SV_TYPE_BACKUP_BROWSER    = 0x00020000
  109. SV_TYPE_MASTER_BROWSER    = 0x00040000
  110. SV_TYPE_DOMAIN_MASTER     = 0x00080000
  111. SV_TYPE_LOCAL_LIST_ONLY = 0x40000000
  112. SV_TYPE_DOMAIN_ENUM     = 0x80000000
  113.  
  114. # Options values for SMB.stor_file and SMB.retr_file
  115. SMB_O_CREAT = 0x10   # Create the file if file does not exists. Otherwise, operation fails.
  116. SMB_O_EXCL = 0x00    # When used with SMB_O_CREAT, operation fails if file exists. Cannot be used with SMB_O_OPEN.
  117. SMB_O_OPEN = 0x01    # Open the file if the file exists
  118. SMB_O_TRUNC = 0x02   # Truncate the file if the file exists
  119.  
  120. # Share Access Mode
  121. SMB_SHARE_COMPAT = 0x00
  122. SMB_SHARE_DENY_EXCL = 0x10
  123. SMB_SHARE_DENY_WRITE = 0x20
  124. SMB_SHARE_DENY_READEXEC = 0x30
  125. SMB_SHARE_DENY_NONE = 0x40
  126. SMB_ACCESS_READ = 0x00
  127. SMB_ACCESS_WRITE = 0x01
  128. SMB_ACCESS_READWRITE = 0x02
  129. SMB_ACCESS_EXEC = 0x03
  130.  
  131. TRANS_DISCONNECT_TID = 1
  132. TRANS_NO_RESPONSE    = 2
  133.  
  134. #*********************************** TEMP BEGIN ********************************
  135. def set_key_odd_parity(key):
  136.     ""
  137.     for i in range(len(key)):
  138.         for k in range(7):
  139.             bit = 0
  140.             t = key[i] >> k
  141.             bit = (t ^ bit) & 0x1
  142.         key[i] = (key[i] & 0xFE) | bit
  143.  
  144.     return key
  145.  
  146. #*********************************** TEMP END ********************************
  147.  
  148. def strerror(errclass, errcode):
  149.     if errclass == 0x01:
  150.         return 'OS error', ERRDOS.get(errcode, 'Unknown error')
  151.     elif errclass == 0x02:
  152.         return 'Server error', ERRSRV.get(errcode, 'Unknown error')
  153.     elif errclass == 0x03:
  154.         return 'Hardware error', ERRHRD.get(errcode, 'Unknown error')
  155.     # This is not a standard error class for SMB
  156.     elif errclass == 0x80:
  157.         return 'Browse error', ERRBROWSE.get(errcode, 'Unknown error')
  158.     elif errclass == 0xff:
  159.         return 'Bad command', 'Bad command. Please file bug report'
  160.     else:
  161.         return 'Unknown error', 'Unknown error'
  162.  
  163.     
  164.  
  165. # Raised when an error has occured during a session
  166. class SessionError(Exception):
  167.     # Error codes
  168.  
  169.  
  170.     # SMB X/Open error codes for the ERRDOS error class
  171.     ERRsuccess = 0
  172.     ERRbadfunc = 1
  173.     ERRbadfile = 2
  174.     ERRbadpath = 3
  175.     ERRnofids = 4
  176.     ERRnoaccess = 5
  177.     ERRbadfid = 6
  178.     ERRbadmcb = 7
  179.     ERRnomem = 8
  180.     ERRbadmem = 9
  181.     ERRbadenv = 10
  182.     ERRbadaccess = 12
  183.     ERRbaddata = 13
  184.     ERRres = 14
  185.     ERRbaddrive = 15
  186.     ERRremcd = 16
  187.     ERRdiffdevice = 17
  188.     ERRnofiles = 18
  189.     ERRgeneral = 31
  190.     ERRbadshare = 32
  191.     ERRlock = 33
  192.     ERRunsup = 50
  193.     ERRnetnamedel = 64
  194.     ERRnosuchshare = 67
  195.     ERRfilexists = 80
  196.     ERRinvalidparam = 87
  197.     ERRcannotopen = 110
  198.     ERRinsufficientbuffer = 122
  199.     ERRinvalidname = 123
  200.     ERRunknownlevel = 124
  201.     ERRnotlocked = 158
  202.     ERRrename = 183
  203.     ERRbadpipe = 230
  204.     ERRpipebusy = 231
  205.     ERRpipeclosing = 232
  206.     ERRnotconnected = 233
  207.     ERRmoredata = 234
  208.     ERRnomoreitems = 259
  209.     ERRbaddirectory = 267
  210.     ERReasnotsupported = 282
  211.     ERRlogonfailure = 1326
  212.     ERRbuftoosmall = 2123
  213.     ERRunknownipc = 2142
  214.     ERRnosuchprintjob = 2151
  215.     ERRinvgroup = 2455
  216.  
  217.     # here's a special one from observing NT
  218.     ERRnoipc = 66
  219.  
  220.     # These errors seem to be only returned by the NT printer driver system
  221.     ERRdriveralreadyinstalled = 1795
  222.     ERRunknownprinterport = 1796
  223.     ERRunknownprinterdriver = 1797
  224.     ERRunknownprintprocessor = 1798
  225.     ERRinvalidseparatorfile = 1799
  226.     ERRinvalidjobpriority = 1800
  227.     ERRinvalidprintername = 1801
  228.     ERRprinteralreadyexists = 1802
  229.     ERRinvalidprintercommand = 1803
  230.     ERRinvaliddatatype = 1804
  231.     ERRinvalidenvironment = 1805
  232.  
  233.     ERRunknownprintmonitor = 3000
  234.     ERRprinterdriverinuse = 3001
  235.     ERRspoolfilenotfound = 3002
  236.     ERRnostartdoc = 3003
  237.     ERRnoaddjob = 3004
  238.     ERRprintprocessoralreadyinstalled = 3005
  239.     ERRprintmonitoralreadyinstalled = 3006
  240.     ERRinvalidprintmonitor = 3007
  241.     ERRprintmonitorinuse = 3008
  242.     ERRprinterhasjobsqueued = 3009
  243.  
  244.     # Error codes for the ERRSRV class
  245.  
  246.     ERRerror = 1
  247.     ERRbadpw = 2
  248.     ERRbadtype = 3
  249.     ERRaccess = 4
  250.     ERRinvnid = 5
  251.     ERRinvnetname = 6
  252.     ERRinvdevice = 7
  253.     ERRqfull = 49
  254.     ERRqtoobig = 50
  255.     ERRinvpfid = 52
  256.     ERRsmbcmd = 64
  257.     ERRsrverror = 65
  258.     ERRfilespecs = 67
  259.     ERRbadlink = 68
  260.     ERRbadpermits = 69
  261.     ERRbadpid = 70
  262.     ERRsetattrmode = 71
  263.     ERRpaused = 81
  264.     ERRmsgoff = 82
  265.     ERRnoroom = 83
  266.     ERRrmuns = 87
  267.     ERRtimeout = 88
  268.     ERRnoresource = 89
  269.     ERRtoomanyuids = 90
  270.     ERRbaduid = 91
  271.     ERRuseMPX = 250
  272.     ERRuseSTD = 251
  273.     ERRcontMPX = 252
  274.     ERRbadPW = None
  275.     ERRnosupport = 0
  276.     ERRunknownsmb = 22
  277.  
  278.     # Error codes for the ERRHRD class
  279.  
  280.     ERRnowrite = 19
  281.     ERRbadunit = 20
  282.     ERRnotready = 21
  283.     ERRbadcmd = 22
  284.     ERRdata = 23
  285.     ERRbadreq = 24
  286.     ERRseek = 25
  287.     ERRbadmedia = 26
  288.     ERRbadsector = 27
  289.     ERRnopaper = 28
  290.     ERRwrite = 29
  291.     ERRread = 30
  292.     ERRgeneral = 31
  293.     ERRwrongdisk = 34
  294.     ERRFCBunavail = 35
  295.     ERRsharebufexc = 36
  296.     ERRdiskfull = 39
  297.  
  298.  
  299.     hard_msgs = {
  300.       19: ("ERRnowrite", "Attempt to write on write-protected diskette."),
  301.       20: ("ERRbadunit", "Unknown unit."),
  302.       21: ("ERRnotready", "Drive not ready."),
  303.       22: ("ERRbadcmd", "Unknown command."),
  304.       23: ("ERRdata", "Data error (CRC)."),
  305.       24: ("ERRbadreq", "Bad request structure length."),
  306.       25 : ("ERRseek", "Seek error."),
  307.       26: ("ERRbadmedia", "Unknown media type."),
  308.       27: ("ERRbadsector", "Sector not found."),
  309.       28: ("ERRnopaper", "Printer out of paper."),
  310.       29: ("ERRwrite", "Write fault."),
  311.       30: ("ERRread", "Read fault."),
  312.       31: ("ERRgeneral", "General failure."),
  313.       32: ("ERRbadshare", "An open conflicts with an existing open."),
  314.       33: ("ERRlock", "A Lock request conflicted with an existing lock or specified an invalid mode, or an Unlock requested attempted to remove a lock held by another process."),
  315.       34: ("ERRwrongdisk", "The wrong disk was found in a drive."),
  316.       35: ("ERRFCBUnavail", "No FCBs are available to process request."),
  317.       36: ("ERRsharebufexc", "A sharing buffer has been exceeded.")
  318.       }
  319.     dos_msgs = {
  320.       ERRbadfunc: ("ERRbadfunc", "Invalid function."),
  321.       ERRbadfile: ("ERRbadfile", "File not found."),
  322.       ERRbadpath: ("ERRbadpath", "Directory invalid."),
  323.       ERRnofids: ("ERRnofids", "No file descriptors available"),
  324.       ERRnoaccess: ("ERRnoaccess", "Access denied."),
  325.       ERRbadfid: ("ERRbadfid", "Invalid file handle."),
  326.       ERRbadmcb: ("ERRbadmcb", "Memory control blocks destroyed."),
  327.       ERRnomem: ("ERRnomem", "Insufficient server memory to perform the requested function."),
  328.       ERRbadmem: ("ERRbadmem", "Invalid memory block address."),
  329.       ERRbadenv: ("ERRbadenv", "Invalid environment."),
  330.       11: ("ERRbadformat", "Invalid format."),
  331.       ERRbadaccess: ("ERRbadaccess", "Invalid open mode."),
  332.       ERRbaddata: ("ERRbaddata", "Invalid data."),
  333.       ERRres: ("ERRres", "reserved."),
  334.       ERRbaddrive: ("ERRbaddrive", "Invalid drive specified."),
  335.       ERRremcd: ("ERRremcd", "A Delete Directory request attempted  to  remove  the  server's  current directory."),
  336.       ERRdiffdevice: ("ERRdiffdevice", "Not same device."),
  337.       ERRnofiles: ("ERRnofiles", "A File Search command can find no more files matching the specified criteria."),
  338.       ERRbadshare: ("ERRbadshare", "The sharing mode specified for an Open conflicts with existing  FIDs  on the file."),
  339.       ERRlock: ("ERRlock", "A Lock request conflicted with an existing lock or specified an  invalid mode,  or an Unlock requested attempted to remove a lock held by another process."),
  340.       ERRunsup: ("ERRunsup",  "The operation is unsupported"),
  341.       ERRnosuchshare: ("ERRnosuchshare",  "You specified an invalid share name"),
  342.       ERRfilexists: ("ERRfilexists", "The file named in a Create Directory, Make  New  File  or  Link  request already exists."),
  343.       ERRinvalidname: ("ERRinvalidname",  "Invalid name"),
  344.       ERRbadpipe: ("ERRbadpipe", "Pipe invalid."),
  345.       ERRpipebusy: ("ERRpipebusy", "All instances of the requested pipe are busy."),
  346.       ERRpipeclosing: ("ERRpipeclosing", "Pipe close in progress."),
  347.       ERRnotconnected: ("ERRnotconnected", "No process on other end of pipe."),
  348.       ERRmoredata: ("ERRmoredata", "There is more data to be returned."),
  349.       ERRinvgroup: ("ERRinvgroup", "Invalid workgroup (try the -W option)"),
  350.       ERRlogonfailure: ("ERRlogonfailure", "Logon failure"),
  351.       ERRdiskfull: ("ERRdiskfull", "Disk full"),
  352.       ERRgeneral: ("ERRgeneral",  "General failure"),
  353.       ERRunknownlevel: ("ERRunknownlevel",  "Unknown info level")
  354.       }
  355.  
  356.     server_msgs = { 
  357.       1: ("ERRerror", "Non-specific error code."),
  358.       2: ("ERRbadpw", "Bad password - name/password pair in a Tree Connect or Session Setup are invalid."),
  359.       3: ("ERRbadtype", "reserved."),
  360.       4: ("ERRaccess", "The requester does not have  the  necessary  access  rights  within  the specified  context for the requested function. The context is defined by the TID or the UID."),
  361.       5: ("ERRinvnid", "The tree ID (TID) specified in a command was invalid."),
  362.       6: ("ERRinvnetname", "Invalid network name in tree connect."),
  363.       7: ("ERRinvdevice", "Invalid device - printer request made to non-printer connection or  non-printer request made to printer connection."),
  364.       49: ("ERRqfull", "Print queue full (files) -- returned by open print file."),
  365.       50: ("ERRqtoobig", "Print queue full -- no space."),
  366.       51: ("ERRqeof", "EOF on print queue dump."),
  367.       52: ("ERRinvpfid", "Invalid print file FID."),
  368.       64: ("ERRsmbcmd", "The server did not recognize the command received."),
  369.       65: ("ERRsrverror","The server encountered an internal error, e.g., system file unavailable."),
  370.       67: ("ERRfilespecs", "The file handle (FID) and pathname parameters contained an invalid  combination of values."),
  371.       68: ("ERRreserved", "reserved."),
  372.       69: ("ERRbadpermits", "The access permissions specified for a file or directory are not a valid combination.  The server cannot set the requested attribute."),
  373.       70: ("ERRreserved", "reserved."),
  374.       71: ("ERRsetattrmode", "The attribute mode in the Set File Attribute request is invalid."),
  375.       81: ("ERRpaused", "Server is paused."),
  376.       82: ("ERRmsgoff", "Not receiving messages."),
  377.       83: ("ERRnoroom", "No room to buffer message."),
  378.       87: ("ERRrmuns", "Too many remote user names."),
  379.       88: ("ERRtimeout", "Operation timed out."),
  380.       89: ("ERRnoresource", "No resources currently available for request."),
  381.       90: ("ERRtoomanyuids", "Too many UIDs active on this session."),
  382.       91: ("ERRbaduid", "The UID is not known as a valid ID on this session."),
  383.       250: ("ERRusempx","Temp unable to support Raw, use MPX mode."),
  384.       251: ("ERRusestd","Temp unable to support Raw, use standard read/write."),
  385.       252: ("ERRcontmpx", "Continue in MPX mode."),
  386.       253: ("ERRreserved", "reserved."),
  387.       254: ("ERRreserved", "reserved."),
  388.   0xFFFF: ("ERRnosupport", "Function not supported.")
  389.   }    
  390.     # Error clases
  391.  
  392.     ERRDOS = 0x1
  393.     error_classes = { 0: ("SUCCESS", {}),
  394.                       ERRDOS: ("ERRDOS", dos_msgs),
  395.                       0x02: ("ERRSRV",server_msgs),
  396.                       0x03: ("ERRHRD",hard_msgs),
  397.                       0x04: ("ERRXOS", {} ),
  398.                       0xE1: ("ERRRMX1", {} ),
  399.                       0xE2: ("ERRRMX2", {} ),
  400.                       0xE3: ("ERRRMX3", {} ),
  401.                       0xFF: ("ERRCMD", {} ) }
  402.  
  403.     
  404.  
  405.     def __init__( self, str, error_class, error_code):
  406.         self.args = str
  407.         self.error_class = error_class
  408.         self.error_code = error_code
  409.  
  410.     def get_error_class( self ):
  411.         return self.error_class
  412.  
  413.     def get_error_code( self ):
  414.         return self.error_code
  415.  
  416.     def __str__( self ):
  417.         error_class = SessionError.error_classes.get( self.error_class, None )
  418.         if not error_class:
  419.             error_code_str = self.error_code
  420.             error_class_str = self.error_class
  421.         else:
  422.             error_class_str = error_class[0]
  423.             error_code = error_class[1].get( self.error_code, None )
  424.             if not error_code:
  425.                 error_code_str = self.error_code
  426.             else:
  427.                 error_code_str = '%s(%s)' % (error_code)
  428.  
  429.         return 'SessionError: %s, class: %s, code: %s' % (self.args, error_class_str, error_code_str)
  430.  
  431.  
  432. # Raised when an supported feature is present/required in the protocol but is not
  433. # currently supported by pysmb
  434. class UnsupportedFeature(Exception): pass
  435.  
  436. # Contains information about a SMB shared device/service
  437. class SharedDevice:
  438.  
  439.     def __init__(self, name, type, comment):
  440.         self.__name = name
  441.         self.__type = type
  442.         self.__comment = comment
  443.  
  444.     def get_name(self):
  445.         return self.__name
  446.  
  447.     def get_type(self):
  448.         return self.__type
  449.  
  450.     def get_comment(self):
  451.         return self.__comment
  452.  
  453.     def __repr__(self):
  454.         return '<SharedDevice instance: name=' + self.__name + ', type=' + str(self.__type) + ', comment="' + self.__comment + '">'
  455.  
  456.  
  457.  
  458. # Contains information about the shared file/directory
  459. class SharedFile:
  460.  
  461.     def __init__(self, ctime, atime, mtime, filesize, allocsize, attribs, shortname, longname):
  462.         self.__ctime = ctime
  463.         self.__atime = atime
  464.         self.__mtime = mtime
  465.         self.__filesize = filesize
  466.         self.__allocsize = allocsize
  467.         self.__attribs = attribs
  468.         try:
  469.             self.__shortname = shortname[:string.index(shortname, '\0')]
  470.         except ValueError:
  471.             self.__shortname = shortname
  472.         try:
  473.             self.__longname = longname[:string.index(longname, '\0')]
  474.         except ValueError:
  475.             self.__longname = longname
  476.  
  477.     def get_ctime(self):
  478.         return self.__ctime
  479.  
  480.     def get_ctime_epoch(self):
  481.         return self.__convert_smbtime(self.__ctime)
  482.  
  483.     def get_mtime(self):
  484.         return self.__mtime
  485.  
  486.     def get_mtime_epoch(self):
  487.         return self.__convert_smbtime(self.__mtime)
  488.  
  489.     def get_atime(self):
  490.         return self.__atime
  491.  
  492.     def get_atime_epoch(self):
  493.         return self.__convert_smbtime(self.__atime)
  494.  
  495.     def get_filesize(self):
  496.         return self.__filesize
  497.  
  498.     def get_allocsize(self):
  499.         return self.__allocsize
  500.  
  501.     def get_attributes(self):
  502.         return self.__attribs
  503.  
  504.     def is_archive(self):
  505.         return self.__attribs & ATTR_ARCHIVE
  506.  
  507.     def is_compressed(self):
  508.         return self.__attribs & ATTR_COMPRESSED
  509.  
  510.     def is_normal(self):
  511.         return self.__attribs & ATTR_NORMAL
  512.  
  513.     def is_hidden(self):
  514.         return self.__attribs & ATTR_HIDDEN
  515.  
  516.     def is_readonly(self):
  517.         return self.__attribs & ATTR_READONLY
  518.  
  519.     def is_temporary(self):
  520.         return self.__attribs & ATTR_TEMPORARY
  521.  
  522.     def is_directory(self):
  523.         return self.__attribs & ATTR_DIRECTORY
  524.  
  525.     def is_system(self):
  526.         return self.__attribs & ATTR_SYSTEM
  527.  
  528.     def get_shortname(self):
  529.         return self.__shortname
  530.  
  531.     def get_longname(self):
  532.         return self.__longname
  533.  
  534.     def __repr__(self):
  535.         return '<SharedFile instance: shortname="' + self.__shortname + '", longname="' + self.__longname + '", filesize=' + str(self.__filesize) + '>'
  536.  
  537.     def __convert_smbtime(self, t):
  538.         x = t >> 32
  539.         y = t & 0xffffffffL
  540.         geo_cal_offset = 11644473600.0  # = 369.0 * 365.25 * 24 * 60 * 60 - (3.0 * 24 * 60 * 60 + 6.0 * 60 * 60)
  541.         return ((x * 4.0 * (1 << 30) + (y & 0xfff00000L)) * 1.0e-7 - geo_cal_offset)
  542.  
  543.  
  544. # Contain information about a SMB machine
  545. class SMBMachine:
  546.  
  547.     def __init__(self, nbname, type, comment):
  548.         self.__nbname = nbname
  549.         self.__type = type
  550.         self.__comment = comment
  551.  
  552.     def __repr__(self):
  553.         return '<SMBMachine instance: nbname="' + self.__nbname + '", type=' + hex(self.__type) + ', comment="' + self.__comment + '">'
  554.  
  555.  
  556.  
  557. class SMBDomain:
  558.  
  559.     def __init__(self, nbgroup, type, master_browser):
  560.         self.__nbgroup = nbgroup
  561.         self.__type = type
  562.         self.__master_browser = master_browser
  563.  
  564.     def __repr__(self):
  565.         return '<SMBDomain instance: nbgroup="' + self.__nbgroup + '", type=' + hex(self.__type) + ', master browser="' + self.__master_browser + '">'
  566.     
  567. # Represents a SMB Packet
  568. class NewSMBPacket(Structure):
  569.     structure = (
  570.         ('Signature', '"\xffSMB'),
  571.         ('Command','B=0'),
  572.         ('ErrorClass','B=0'),
  573.         ('_reserved','B=0'),
  574.         ('ErrorCode','<H=0'),
  575.         ('Flags1','B=0'),
  576.         ('Flags2','<H=0'),
  577.         ('Padding','12s=""'),
  578.         ('Tid','<H=0xffff'),
  579.         ('Pid','<H=0'),
  580.         ('Uid','<H=0'),
  581.         ('Mid','<H=0'),
  582.         ('Data','*:'),
  583.     )
  584.  
  585.     def __init__(self, **kargs):
  586.         Structure.__init__(self, **kargs)
  587.  
  588.         if not kargs.has_key('data'):
  589.             self['Data'] = []
  590.  
  591.     def addCommand(self, command):
  592.         if len(self['Data']) == 0:
  593.             self['Command'] = command.command
  594.         else:
  595.             self['Data'][-1]['Parameters']['AndXCommand'] = command.command
  596.             self['Data'][-1]['Parameters']['AndXOffset'] = len(self)
  597.         self['Data'].append(command)
  598.         
  599.     def isMoreData(self):
  600.         return (self['Command'] in [SMB.SMB_COM_TRANSACTION, SMB.SMB_COM_READ_ANDX, SMB.SMB_COM_READ_RAW] and
  601.                 self['ErrorClass'] == 1 and self['ErrorCode'] == SessionError.ERRmoredata)
  602.  
  603.     def isValidAnswer(self, cmd):
  604.         # this was inside a loop reading more from the net (with recv_packet(None))
  605.         if self['Command'] == cmd:
  606.             if (self['ErrorClass'] == 0x00 and
  607.                 self['ErrorCode']  == 0x00):
  608.                     return 1
  609.             elif self.isMoreData():
  610.                 return 1
  611.             raise SessionError, ("SMB Library Error", self['ErrorClass'], self['ErrorCode'])
  612.         else:
  613.             raise UnsupportedFeature, ("Unexpected answer from server: Got %d, Expected %d" % (self['Command'], cmd))
  614.  
  615. class SMBPacket:
  616.     def __init__(self,data = ''):
  617.         # The uid attribute will be set when the client calls the login() method
  618.         self._command = 0x0
  619.         self._error_class = 0x0
  620.         self._error_code = 0x0
  621.         self._flags = 0x0
  622.         self._flags2 = 0x0
  623.         self._pad = '\0' * 12
  624.         self._tid = 0x0
  625.         self._pid = 0x0
  626.         self._uid = 0x0
  627.         self._mid = 0x0
  628.         self._wordcount = 0x0
  629.         self._parameter_words = ''
  630.         self._bytecount = 0x0
  631.         self._buffer = ''
  632.         if data != '':
  633.             self._command = ord(data[4])
  634.             self._error_class = ord(data[5])
  635.             self._error_code = unpack('<H',data[7:9])[0]
  636.             self._flags = ord(data[9])
  637.             self._flags2 = unpack('<H',data[10:12])[0]
  638.             self._tid = unpack('<H',data[24:26])[0]
  639.             self._pid = unpack('<H',data[26:28])[0]
  640.             self._uid = unpack('<H',data[28:30])[0]
  641.             self._mid = unpack('<H',data[30:32])[0]
  642.             self._wordcount = ord(data[32])
  643.             self._parameter_words = data[33:33+self._wordcount*2]
  644.             self._bytecount = ord(data[33+self._wordcount*2])
  645.             self._buffer = data[35+self._wordcount*2:]
  646.     def set_command(self,command):
  647.         self._command = command
  648.     def set_error_class(self, error_class):
  649.         self._error_class = error_class
  650.     def set_error_code(self,error_code):
  651.         self._error_code = error_code
  652.     def set_flags(self,flags):
  653.         self._flags = flags
  654.     def set_flags2(self, flags2):
  655.         self._flags2 = flags2
  656.     def set_pad(self, pad):
  657.         self._pad = pad
  658.     def set_tid(self,tid):
  659.         self._tid = tid
  660.     def set_pid(self,pid):
  661.         self._pid = pid
  662.     def set_uid(self,uid):
  663.         self._uid = uid
  664.     def set_mid(self,mid):
  665.         self._mid = mid
  666.     def set_parameter_words(self,param):
  667.         self._parameter_words = param
  668.         self._wordcount = len(param)/2
  669.     def set_buffer(self,buffer):
  670.         if type(buffer) is types.UnicodeType:
  671.             raise Exception('SMBPacket: Invalid buffer. Received unicode')
  672.         self._buffer = buffer
  673.         self._bytecount = len(buffer)
  674.  
  675.     def get_command(self):
  676.         return self._command
  677.     def get_error_class(self):
  678.         return self._error_class
  679.     def get_error_code(self):
  680.         return self._error_code
  681.     def get_flags(self):
  682.         return self._flags
  683.     def get_flags2(self):
  684.         return self._flags2
  685.     def get_pad(self):
  686.         return self._pad
  687.     def get_tid(self):
  688.         return self._tid
  689.     def get_pid(self):
  690.         return self._pid
  691.     def get_uid(self):
  692.         return self._uid
  693.     def get_mid(self):
  694.         return self._mid
  695.     def get_parameter_words(self):
  696.         return self._parameter_words
  697.     def get_wordcount(self):
  698.         return self._wordcount
  699.     def get_bytecount(self):
  700.         return self._bytecount
  701.     def get_buffer(self):
  702.         return self._buffer
  703.     def rawData(self):
  704.         data = pack('<4sBBBHBH12sHHHHB','\xffSMB',self._command,self._error_class,0,self._error_code,self._flags,
  705.                     self._flags2,self._pad,self._tid, self._pid, self._uid, self._mid, self._wordcount) + self._parameter_words + pack('<H',self._bytecount) + self._buffer
  706.         return data        
  707.  
  708. class TRANSHeader:
  709.     def __init__(self,params = '', data = ''):
  710.         self._total_param_count = 0
  711.         self._total_data_count = 0
  712.         self._max_param_count = 0
  713.         self._max_data_count = 0
  714.         self._max_setup_count = 0
  715.         self._flags = 0
  716.         self._timeout = 0
  717.         self._param_count = 0
  718.         self._param_offset = 0
  719.         self._data_count = 0
  720.         self._data_offset = 0
  721.         self._setup_count = 0
  722.         self._setup = 0
  723.         self._name = ''
  724.         self._pad = ''
  725.         self._parameters = 0
  726.         self._data = 0
  727.         if data != '' and params != '':
  728.             self._total_param_count, self._total_data_count, _, self._param_count, self._param_offset, self._param_displacement, self._data_count, self._data_offset, self._data_displacement, self._setup_count, _ = unpack ('<HHHHHHHHHBB', params)
  729.             self._data = data[-self._data_count:]; # Remove -potential- prefix padding.
  730.             
  731.     def set_flags(self, flags):
  732.         self._flags = flags
  733.     def set_name(self,name):
  734.         self._name = name
  735.     def set_setup(self,setup):
  736.         self._setup = setup
  737.     def set_parameters(self,parameters):
  738.         self._parameters = parameters
  739.         self._total_param_count = len(parameters)
  740.     def set_data(self, data):
  741.         self._data = data
  742.         self._total_data_count = len(data)
  743.     def set_max_data_count(self, max):
  744.         self._max_data_count = max
  745.     def set_max_param_count(self, max):
  746.         self._max_param_count = max
  747.     def get_rawParameters(self):
  748.         self._param_offset = 32+3+28+len(self._setup)+len(self._name)
  749.         self._data_offset = self._param_offset + len(self._parameters)
  750.         return pack('<HHHHBBHLHHHHHBB', self._total_param_count, self._total_data_count, self._max_param_count, self._max_data_count, self._max_setup_count,
  751.                     0,self._flags, self._timeout, 0, self._total_param_count, self._param_offset , self._total_data_count, self._data_offset, len(self._setup) / 2,0 ) + self._setup
  752.     def get_data(self):
  753.         return self._data
  754.     def rawData(self):
  755.         return self._name +  self._parameters + self._data
  756.  
  757. class SMBCommand(Structure):
  758.     structure = (
  759.         ('WordCount', 'B=len(Parameters)/2'),
  760.         ('_ParametersLength','_-Parameters','WordCount*2'),
  761.         ('Parameters',':'),             # default set by constructor
  762.         ('ByteCount','<H-Data'),
  763.         ('Data',':'),                   # default set by constructor
  764.     )
  765.  
  766.     def __init__(self, commandOrData = None, data = None, **kargs):
  767.         if type(commandOrData) == type(0):
  768.             self.command = commandOrData
  769.         else:
  770.             data = data or commandOrData
  771.  
  772.         Structure.__init__(self, data = data, **kargs)
  773.  
  774.         if data is None:
  775.             self['Parameters'] = ''
  776.             self['Data']       = ''
  777.  
  778. class AsciiOrUnicodeStructure(Structure):
  779.     def __init__(self, flags = 0, **kargs):
  780.         if flags & SMB.FLAGS2_UNICODE:
  781.             self.structure = self.UnicodeStructure
  782.         else:
  783.             self.structure = self.AsciiStructure
  784.         return Structure.__init__(self, **kargs)
  785.  
  786. class SMBCommand_Parameters(Structure):
  787.     pass
  788.  
  789. class SMBAndXCommand_Parameters(Structure):
  790.     commonHdr = (
  791.         ('AndXCommand','B=0xff'),
  792.         ('_reserved','B=0'),
  793.         ('AndXOffset','<H=0'),
  794.     )
  795.     structure = (       # default structure, overriden by subclasses
  796.         ('Data',':=""'),
  797.     )
  798.  
  799. class SMBSessionSetupAndX_Parameters(SMBAndXCommand_Parameters):
  800.     structure = (
  801.         ('MaxBuffer','<H'),
  802.         ('MaxMpxCount','<H'),
  803.         ('VCNumber','<H'),
  804.         ('SessionKey','<L'),
  805.         ('AnsiPwdLength','<H'),
  806.         ('UnicodePwdLength','<H'),
  807.         ('_reserved','<L=0'),
  808.         ('Capabilities','<L'),
  809.     )
  810.  
  811. class SMBSessionSetupAndX_Data(AsciiOrUnicodeStructure):
  812.     AsciiStructure = (
  813.         ('AnsiPwdLength','_-AnsiPwd'),
  814.         ('UnicodePwdLength','_-UnicodePwd'),
  815.         ('AnsiPwd',':=""'),
  816.         ('UnicodePwd',':=""'),
  817.         ('Account','z=""'),
  818.         ('PrimaryDomain','z=""'),
  819.         ('NativeOS','z=""'),
  820.         ('NativeLanMan','z=""'),
  821.     )
  822.     
  823.     UnicodeStructure = (
  824.         ('AnsiPwdLength','_-AnsiPwd'),
  825.         ('UnicodePwdLength','_-UnicodePwd'),
  826.         ('AnsiPwd',':=""'),
  827.         ('UnicodePwd',':=""'),
  828.         ('Account','w=""'),
  829.         ('PrimaryDomain','w=""'),
  830.         ('NativeOS','w=""'),
  831.         ('NativeLanMan','w=""'),
  832.     )
  833.  
  834. class SMBSessionSetupAndXResponse_Parameters(SMBAndXCommand_Parameters):
  835.     structure = (
  836.         ('Action','<H'),
  837.     )
  838.  
  839. class SMBSessionSetupAndXResponse_Data(AsciiOrUnicodeStructure):
  840.     AsciiStructure = (
  841.         ('NativeOS','z=""'),
  842.         ('NativeLanMan','z=""'),
  843.         ('PrimaryDomain','z=""'),
  844.     )
  845.  
  846.     UnicodeStructure = (
  847.         ('NativeOS','w=""'),
  848.         ('NativeLanMan','w=""'),
  849.         ('PrimaryDomain','w=""'),
  850.     )
  851.  
  852. class SMBTreeConnect_Parameters(SMBCommand_Parameters):
  853.     structure = (
  854.     )
  855.  
  856. class SMBTreeConnect_Data(SMBCommand_Parameters):
  857.     structure = (
  858.         ('PathFormat','"\x04'),
  859.         ('Path','z'),
  860.         ('PasswordFormat','"\x04'),
  861.         ('Password','z'),
  862.         ('ServiceFormat','"\x04'),
  863.         ('Service','z'),
  864.     )
  865. class SMBTreeConnectAndX_Parameters(SMBAndXCommand_Parameters):
  866.     structure = (
  867.         ('Flags','<H=0'),
  868.         ('PasswordLength','<H'),
  869.     )
  870.  
  871. class SMBTreeConnectAndX_Data(SMBCommand_Parameters):
  872.     structure = (
  873.         ('_PasswordLength','_-Password'),
  874.         ('Password',':'),
  875.         ('Path','z'),
  876.         ('Service','z'),
  877.     )
  878.  
  879. class SMBNtCreateAndX_Parameters(SMBAndXCommand_Parameters):
  880.     structure = (
  881.         ('_reserved', 'B=0'),
  882.         ('FileNameLength','<H'),
  883.         ('CreateFlags','<L'),
  884.         ('RootFid','<L=0'),
  885.         ('AccessMask','<L'),
  886.         ('AllocationSizeLo','<L=0'),
  887.         ('AllocationSizeHi','<L=0'),
  888.         ('FileAttributes','<L=0'),
  889.         ('ShareAccess','<L=3'),
  890.         ('Disposition','<L=1'),
  891.         ('CreateOptions','<L'),
  892.         ('Impersonation','<L=2'),
  893.         ('SecurityFlags','B=3'),
  894.     )
  895.  
  896. class SMBNtCreateAndXResponse_Parameters(SMBAndXCommand_Parameters):
  897.     # XXX Is there a memory leak in the response for NTCreate (where the Data section would be) in Win 2000, Win XP, and Win 2003?
  898.     structure = (
  899.         ('OplockLevel', 'B=0'),
  900.         ('Fid','<H'),
  901.         ('CreateAction','<L'),
  902.         ('CraetionTimeLo','<L=0'),
  903.         ('CraetionTimeHi','<L=0'),
  904.         ('AccessTimeLo','<L=0'),
  905.         ('AccessTimeHi','<L=0'),
  906.         ('LastWriteTimeLo','<L=0'),
  907.         ('LastWriteTimeHi','<L=0'),
  908.         ('ChangeTimeLo','<L=0'),
  909.         ('ChangeTimeHi','<L=0'),
  910.         ('FileAttributes','<L=0x80'),
  911.         ('AllocationSizeLo','<L=0'),
  912.         ('AllocationSizeHi','<L=0'),
  913.         ('EndOfFileLo','<L=0'),
  914.         ('EndOfFileHi','<L=0'),
  915.         ('FileType','<H=0'),
  916.         ('IPCState','<H=0'),
  917.         ('IsDirectory','B'),
  918.     )
  919.  
  920. class SMBNtCreateAndX_Data(Structure):
  921.     structure = (
  922.         ('FileName','z'),
  923.     )
  924.  
  925. class SMBOpenAndX_Parameters(SMBAndXCommand_Parameters):
  926.     structure = (
  927.         ('Flags','<H=0'),
  928.         ('DesiredAccess','<H=0'),
  929.         ('SearchAttributes','<H=0'),
  930.         ('FileAttributes','<H=0'),
  931.         ('CreationTime','<L=0'),
  932.         ('OpenMode','<H=1'),        # SMB_O_OPEN = 1
  933.         ('AllocationSize','<L=0'),
  934.         ('Reserved','8s=""'),
  935.     )
  936.  
  937. class SMBOpenAndX_Data(SMBNtCreateAndX_Data):
  938.     pass
  939.  
  940. class SMBOpenAndXResponse_Parameters(SMBAndXCommand_Parameters):
  941.     structure = (
  942.         ('Fid','<H=0'),
  943.         ('FileAttributes','<H=0'),
  944.         ('LastWriten','<L=0'),
  945.         ('FileSize','<L=0'),
  946.         ('GrantedAccess','<H=0'),
  947.         ('FileType','<H=0'),
  948.         ('IPCState','<H=0'),
  949.         ('Action','<H=0'),
  950.         ('ServerFid','<L=0'),
  951.         ('_reserved','<H=0'),
  952.     )
  953.  
  954. class SMBWrite_Parameters(SMBCommand_Parameters):
  955.     structure = (
  956.         ('Fid','<H'),
  957.         ('Count','<H'),
  958.         ('Offset','<L'),
  959.         ('Remaining','<H'),
  960.     )
  961.  
  962. class SMBWrite_Data(Structure):
  963.     structure = (
  964.         ('BufferFormat','<B=1'),
  965.         ('DataLength','<H-Data'),
  966.         ('Data',':'),
  967.     )
  968.     
  969. class SMBWriteAndX_Parameters(SMBAndXCommand_Parameters):
  970.     structure = (
  971.         ('Fid','<H'),
  972.         ('Offset','<L'),
  973.         ('_reserved','<L=0xff'),
  974.         ('WriteMode','<H=8'),
  975.         ('Remaining','<H'),
  976.         ('DataLength_Hi','<H=0'),
  977.         ('DataLength','<H'),
  978.         ('DataOffset','<H=0'),
  979.         ('HighOffset','<L=0'),
  980.     )
  981.     
  982. class SMBWriteRaw_Parameters(SMBCommand_Parameters):
  983.     structure = (
  984.         ('Fid','<H'),
  985.         ('Count','<H'),
  986.         ('_reserved','<H=0'),
  987.         ('Offset','<L'),
  988.         ('Timeout','<L=0'),
  989.         ('WriteMode','<H=0'),
  990.         ('_reserved2','<L=0'),
  991.         ('DataLength','<H'),
  992.         ('DataOffset','<H=0'),
  993.     )
  994.     
  995. class SMBRead_Parameters(SMBCommand_Parameters):
  996.     structure = (
  997.         ('Fid','<H'),
  998.         ('Count','<H'),
  999.         ('Offset','<L'),
  1000.         ('Remaining','<H=Count'),
  1001.     )
  1002.  
  1003. class SMBReadResponse_Parameters(Structure):
  1004.     structure = (
  1005.         ('Count','<H=0'),
  1006.         ('_reserved','"\0\0\0\0\0\0\0\0'),
  1007.     )
  1008.  
  1009. class SMBReadResponse_Data(Structure):
  1010.     structure = (
  1011.         ('BufferFormat','<B'),
  1012.         ('DataLength','<H-Data'),
  1013.         ('Data',':'),
  1014.     )
  1015.  
  1016. class SMBReadRaw_Parameters(SMBCommand_Parameters):
  1017.     structure = (
  1018.         ('Fid','<H'),
  1019.         ('Offset','<L'),
  1020.         ('MaxCount','<H'),
  1021.         ('MinCount','<H=MaxCount'),
  1022.         ('Timeout','<L=0'),
  1023.         ('_reserved','<H=0'),
  1024.     )
  1025.  
  1026. class SMBReadAndX_Parameters(SMBAndXCommand_Parameters):
  1027.     structure = (
  1028.         ('Fid','<H'),
  1029.         ('Offset','<L'),
  1030.         ('MaxCount','<H'),
  1031.         ('MinCount','<H=MaxCount'),
  1032.         ('_reserved','<L=0xffffffff'),
  1033.         ('Remaining','<H=MaxCount'),
  1034.         ('HighOffset','<L=0'),
  1035.     )
  1036.  
  1037. class SMBReadAndXResponse_Parameters(SMBAndXCommand_Parameters):
  1038.     structure = (
  1039.         ('Remaining','<H=0'),
  1040.         ('DataMode','<H=0'),
  1041.         ('_reserved','<H=0'),
  1042.         ('DataCount','<H'),
  1043.         ('DataOffset','<H'),
  1044.         ('DataCount_Hi','<L'),
  1045.         ('_reserved2','"\0\0\0\0\0\0'),
  1046.     )
  1047. class SMBOpen_Parameters(SMBCommand_Parameters):
  1048.     structure = (
  1049.         ('DesiredAccess','<H=0'),
  1050.         ('SearchAttributes','<H=0'),
  1051.     )
  1052.  
  1053. class SMBOpen_Data(Structure):
  1054.     structure = (
  1055.         ('FileNameFormat','"\x04'),
  1056.         ('FileName','z'),
  1057.     )
  1058.  
  1059. class SMBOpenResponse_Parameters(SMBCommand_Parameters):
  1060.     structure = (
  1061.         ('Fid','<H=0'),
  1062.         ('FileAttributes','<H=0'),
  1063.         ('LastWriten','<L=0'),
  1064.         ('FileSize','<L=0'),
  1065.         ('GrantedAccess','<H=0'),
  1066.     )
  1067.  
  1068. class NTLMDialect(SMBPacket):
  1069.     def __init__(self,data=''):
  1070.         SMBPacket.__init__(self,data)
  1071.         self._selected_dialect = 0
  1072.         self._security_mode = 0
  1073.         self._max_mpx = 0
  1074.         self._max_vc = 0
  1075.         self._max_buffer = 0
  1076.         self._max_raw = 0
  1077.         self._session_key = 0
  1078.         self._lsw_capabilities = 0
  1079.         self._msw_capabilities = 0
  1080.         self._utc_high = 0
  1081.         self._utc_low = 0
  1082.         self._minutes_utc = 0
  1083.         self._encryption_key_len = 0
  1084.         self._encryption_key = ''
  1085.         self._server_domain = ''
  1086.         self._server_name = ''
  1087.         if data:
  1088.             self._selected_dialect, self._security_mode, self._max_mpx, self._max_vc = unpack('<HBHH',self.get_parameter_words()[:7])
  1089.             self._max_buffer,self._max_raw, self._session_key, self._lsw_capabilities, self._msw_capabilities = unpack('<lllHH', self.get_parameter_words()[7:16+7])
  1090.             self._utc_low, self._utc_high,self._minutes_utc, self._encryption_key_len = unpack('<LLhB',self.get_parameter_words()[23:34])
  1091.             if self._encryption_key_len > 0 and len(self.get_buffer()) >= self._encryption_key_len:
  1092.                 self._encryption_key = self.get_buffer()[:self._encryption_key_len]
  1093.                 buf = self.get_buffer() 
  1094.                 # Look for the server domain offset
  1095.                 self._server_name = '<Unknown>'
  1096.                 self._server_domain = '<Unknown>'
  1097.                 try:
  1098.                     if self._lsw_capabilities & 0x3: # is this unicode?
  1099.                          offset = self._encryption_key_len
  1100.                          if offset & 0x01:
  1101.                             offset += 1
  1102.                          end = offset
  1103.                          while ord(buf[end]) or ord(buf[end+1]):
  1104.                              end += 2
  1105.                          self._server_domain = unicode(buf[offset:end],'utf_16_le')
  1106.                          end += 2
  1107.                          offset = end
  1108.                          while ord(buf[end]) or ord(buf[end+1]):
  1109.                              end += 2
  1110.                          self._server_name = unicode(buf[offset:end],'utf_16_le')
  1111.                     else:
  1112.                          offset = self._encryption_key_len
  1113.                          idx1 = string.find(buf,'\0',offset)
  1114.                          if idx1 != -1:
  1115.                             self._server_domain = buf[offset:idx1]
  1116.                             idx2 = string.find(buf, '\0', idx1 + 1)
  1117.                             if idx2 != -1:
  1118.                                self._server_name = buf[idx1+1:idx2]
  1119.                 except:
  1120.                     pass
  1121.             else:
  1122.                 self._encryption_key = ''
  1123.  
  1124.     def get_selected_dialect(self):
  1125.         return self._selected_dialect
  1126.     def get_security_mode(self):
  1127.         return self._security_mode
  1128.     def get_max_mpx(self):
  1129.         return self._max_mpx
  1130.     def get_max_vc(self):
  1131.         return self._max_vc
  1132.     def get_max_buffer(self):
  1133.         return self._max_buffer
  1134.     def get_max_raw(self):
  1135.         return self._max_raw
  1136.     def get_session_key(self):
  1137.         return self._session_key
  1138.     def get_lsw_capabilities(self):
  1139.         return self._lsw_capabilities
  1140.     def get_msw_capabilities(self):
  1141.         return self._msw_capabilities
  1142.     def get_utc(self):
  1143.         return self._utc_high, self._utc_low
  1144.     def get_minutes_utc(self):
  1145.         return self._minutes_utc
  1146.     def get_encryption_key_len(self):
  1147.         return self._encryption_key_len
  1148.     def get_encryption_key(self):
  1149.         return self._encryption_key
  1150.     def get_server_domain(self):
  1151.         return self._server_domain
  1152.     def get_server_name(self):
  1153.         return self._server_name
  1154.     def is_auth_mode(self):
  1155.         return self._security_mode & SMB.SECURITY_AUTH_MASK
  1156.     def is_share_mode(self):
  1157.         return self._security_mode & SMB.SECURITY_SHARE_MASK
  1158.     def is_rawmode(self):
  1159.         return self._lsw_capabilities & SMB.CAP_RAW_MODE
  1160.                 
  1161.                 
  1162. class SMB:
  1163.  
  1164.     # SMB Command Codes
  1165.     SMB_COM_CREATE_DIRECTORY = 0x00
  1166.     SMB_COM_DELETE_DIRECTORY = 0x01
  1167.     SMB_COM_OPEN = 0x02
  1168.     SMB_COM_CREATE = 0x03
  1169.     SMB_COM_CLOSE = 0x04
  1170.     SMB_COM_FLUSH = 0x05
  1171.     SMB_COM_DELETE = 0x06
  1172.     SMB_COM_RENAME = 0x07
  1173.     SMB_COM_QUERY_INFORMATION = 0x08
  1174.     SMB_COM_SET_INFORMATION = 0x09
  1175.     SMB_COM_READ = 0x0A
  1176.     SMB_COM_WRITE = 0x0B
  1177.     SMB_COM_LOCK_BYTE_RANGE = 0x0C
  1178.     SMB_COM_UNLOCK_BYTE_RANGE = 0x0D
  1179.     SMB_COM_CREATE_TEMPORARY = 0x0E
  1180.     SMB_COM_CREATE_NEW = 0x0F
  1181.     SMB_COM_CHECK_DIRECTORY = 0x10
  1182.     SMB_COM_PROCESS_EXIT = 0x11
  1183.     SMB_COM_SEEK = 0x12
  1184.     SMB_COM_LOCK_AND_READ = 0x13
  1185.     SMB_COM_WRITE_AND_UNLOCK = 0x14
  1186.     SMB_COM_READ_RAW = 0x1A
  1187.     SMB_COM_READ_MPX = 0x1B
  1188.     SMB_COM_READ_MPX_SECONDARY = 0x1C
  1189.     SMB_COM_WRITE_RAW = 0x1D
  1190.     SMB_COM_WRITE_MPX = 0x1E
  1191.     SMB_COM_WRITE_MPX_SECONDARY = 0x1F
  1192.     SMB_COM_WRITE_COMPLETE = 0x20
  1193.     SMB_COM_QUERY_SERVER = 0x21
  1194.     SMB_COM_SET_INFORMATION2 = 0x22
  1195.     SMB_COM_QUERY_INFORMATION2 = 0x23
  1196.     SMB_COM_LOCKING_ANDX = 0x24
  1197.     SMB_COM_TRANSACTION = 0x25
  1198.     SMB_COM_TRANSACTION_SECONDARY = 0x26
  1199.     SMB_COM_IOCTL = 0x27
  1200.     SMB_COM_IOCTL_SECONDARY = 0x28
  1201.     SMB_COM_COPY = 0x29
  1202.     SMB_COM_MOVE = 0x2A
  1203.     SMB_COM_ECHO = 0x2B
  1204.     SMB_COM_WRITE_AND_CLOSE = 0x2C
  1205.     SMB_COM_OPEN_ANDX = 0x2D
  1206.     SMB_COM_READ_ANDX = 0x2E
  1207.     SMB_COM_WRITE_ANDX = 0x2F
  1208.     SMB_COM_NEW_FILE_SIZE = 0x30
  1209.     SMB_COM_CLOSE_AND_TREE_DISC = 0x31
  1210.     SMB_COM_TRANSACTION2 = 0x32
  1211.     SMB_COM_TRANSACTION2_SECONDARY = 0x33
  1212.     SMB_COM_FIND_CLOSE2 = 0x34
  1213.     SMB_COM_FIND_NOTIFY_CLOSE = 0x35
  1214.     # Used by Xenix/Unix 0x60 - 0x6E 
  1215.     SMB_COM_TREE_CONNECT = 0x70
  1216.     SMB_COM_TREE_DISCONNECT = 0x71
  1217.     SMB_COM_NEGOTIATE = 0x72
  1218.     SMB_COM_SESSION_SETUP_ANDX = 0x73
  1219.     SMB_COM_LOGOFF_ANDX = 0x74
  1220.     SMB_COM_TREE_CONNECT_ANDX = 0x75
  1221.     SMB_COM_QUERY_INFORMATION_DISK = 0x80
  1222.     SMB_COM_SEARCH = 0x81
  1223.     SMB_COM_FIND = 0x82
  1224.     SMB_COM_FIND_UNIQUE = 0x83
  1225.     SMB_COM_FIND_CLOSE = 0x84
  1226.     SMB_COM_NT_TRANSACT = 0xA0
  1227.     SMB_COM_NT_TRANSACT_SECONDARY = 0xA1
  1228.     SMB_COM_NT_CREATE_ANDX = 0xA2
  1229.     SMB_COM_NT_CANCEL = 0xA4
  1230.     SMB_COM_NT_RENAME = 0xA5
  1231.     SMB_COM_OPEN_PRINT_FILE = 0xC0
  1232.     SMB_COM_WRITE_PRINT_FILE = 0xC1
  1233.     SMB_COM_CLOSE_PRINT_FILE = 0xC2
  1234.     SMB_COM_GET_PRINT_QUEUE = 0xC3
  1235.     SMB_COM_READ_BULK = 0xD8
  1236.     SMB_COM_WRITE_BULK = 0xD9
  1237.     SMB_COM_WRITE_BULK_DATA = 0xDA
  1238.  
  1239.     # Security Share Mode (Used internally by SMB class)
  1240.     SECURITY_SHARE_MASK = 0x01
  1241.     SECURITY_SHARE_SHARE = 0x00
  1242.     SECURITY_SHARE_USER = 0x01
  1243.     
  1244.     # Security Auth Mode (Used internally by SMB class)
  1245.     SECURITY_AUTH_MASK = 0x02
  1246.     SECURITY_AUTH_ENCRYPTED = 0x02
  1247.     SECURITY_AUTH_PLAINTEXT = 0x00
  1248.  
  1249.     # Raw Mode Mask (Used internally by SMB class. Good for dialect up to and including LANMAN2.1)
  1250.     RAW_READ_MASK = 0x01
  1251.     RAW_WRITE_MASK = 0x02
  1252.  
  1253.     # Capabilities Mask (Used internally by SMB class. Good for dialect NT LM 0.12)
  1254.     CAP_RAW_MODE = 0x0001
  1255.     CAP_MPX_MODE = 0x0002
  1256.     CAP_UNICODE = 0x0004
  1257.     CAP_LARGE_FILES = 0x0008
  1258.     CAP_EXTENDED_SECURITY = 0x80000000
  1259.  
  1260.     # Flags1 Mask
  1261.     FLAGS1_PATHCASELESS = 0x08
  1262.  
  1263.     # Flags2 Mask
  1264.     FLAGS2_LONG_FILENAME = 0x0001
  1265.     FLAGS2_USE_NT_ERRORS = 0x4000
  1266.     FLAGS2_UNICODE = 0x8000
  1267.  
  1268.     def __init__(self, remote_name, remote_host, my_name = None, host_type = nmb.TYPE_SERVER, sess_port = nmb.NETBIOS_SESSION_PORT, timeout=None):
  1269.         # The uid attribute will be set when the client calls the login() method
  1270.         self.__uid = 0
  1271.         self.__server_os = ''
  1272.         self.__server_lanman = ''
  1273.         self.__server_domain = ''
  1274.         self.__remote_name = string.upper(remote_name)
  1275.         self.__is_pathcaseless = 0
  1276.         self.__ntlm_dialect = 0
  1277.         self.__sess = None
  1278.  
  1279.         if timeout==None:
  1280.             self.__timeout = 30
  1281.         else:
  1282.             self.__timeout = timeout
  1283.         
  1284.         if not my_name:
  1285.             my_name = socket.gethostname()
  1286.             i = string.find(my_name, '.')
  1287.             if i > -1:
  1288.                 my_name = my_name[:i]
  1289.  
  1290.         try:
  1291.             self.__sess = nmb.NetBIOSSession(my_name, remote_name, remote_host, host_type, sess_port, timeout)
  1292.         except socket.error, ex:
  1293.             raise ex
  1294.  
  1295.         # Initialize values __ntlm_dialect, __is_pathcaseless
  1296.         self.__neg_session()
  1297.         
  1298.         # If the following assertion fails, then mean that the encryption key is not sent when
  1299.         # encrypted authentication is required by the server.
  1300.         assert (self.__ntlm_dialect.is_auth_mode() == SMB.SECURITY_AUTH_PLAINTEXT) or (self.__ntlm_dialect.is_auth_mode() == SMB.SECURITY_AUTH_ENCRYPTED and self.__ntlm_dialect.get_encryption_key() and self.__ntlm_dialect.get_encryption_key_len() >= 8)
  1301.  
  1302.         # Call login() without any authentication information to setup a session if the remote server
  1303.         # is in share mode.
  1304.         if self.__ntlm_dialect.is_share_mode() == SMB.SECURITY_SHARE_SHARE:
  1305.             self.login('', '')
  1306.             
  1307.     def set_timeout(self, timeout):
  1308.         self.__timeout = timeout
  1309.         
  1310.     def __del__(self):
  1311.         if self.__sess:
  1312.             self.__sess.close()
  1313.  
  1314.     def __decode_smb(self, data):
  1315.         _, cmd, err_class, _, err_code, flags1, flags2, _, tid, pid, uid, mid, wcount = unpack('<4sBBBHBH12sHHHHB', data[:33])
  1316.         param_end = 33 + wcount * 2
  1317.         return cmd, err_class, err_code, flags1, flags2, tid, uid, mid, data[33:param_end], data[param_end + 2:]
  1318.  
  1319.     def recvSMB(self):
  1320.         r = self.__sess.recv_packet(self.__timeout)
  1321.         return NewSMBPacket(data = r.get_trailer())
  1322.     
  1323.     def recv_packet(self):
  1324.         r = self.__sess.recv_packet(self.__timeout)
  1325.         return SMBPacket(r.get_trailer())
  1326.     
  1327.     def __decode_trans(self, params, data):
  1328.         totparamcnt, totdatacnt, _, paramcnt, paramoffset, paramds, datacnt, dataoffset, datads, setupcnt = unpack('<HHHHHHHHHB', params[:19])
  1329.         if paramcnt + paramds < totparamcnt or datacnt + datads < totdatacnt:
  1330.             has_more = 1
  1331.         else:
  1332.             has_more = 0
  1333.         paramoffset = paramoffset - 55 - setupcnt * 2
  1334.         dataoffset = dataoffset - 55 - setupcnt * 2
  1335.         return has_more, params[20:20 + setupcnt * 2], data[paramoffset:paramoffset + paramcnt], data[dataoffset:dataoffset + datacnt]
  1336.  
  1337.     def sendSMB(self,smb):
  1338.         smb['Uid'] = self.__uid
  1339.         smb['Pid'] = os.getpid()
  1340.         self.__sess.send_packet(str(smb))
  1341.  
  1342.     def send_smb(self,s):
  1343.         s.set_uid(self.__uid)
  1344.         s.set_pid(os.getpid())
  1345.         self.__sess.send_packet(s.rawData())
  1346.  
  1347.     def __send_smb_packet(self, cmd, flags, flags2, tid, mid, params = '', data = ''):
  1348.         smb = NewSMBPacket()
  1349.         smb['Flags'] = flags
  1350.         smb['Flags2'] = flags2
  1351.         smb['Tid'] = tid
  1352.         smb['Mid'] = mid
  1353.         cmd = SMBCommand(cmd)
  1354.         smb.addCommand(cmd)
  1355.  
  1356.         cmd['Parameters'] = params
  1357.         cmd['Data'] = data
  1358.         self.sendSMB(smb)
  1359.  
  1360.     def isValidAnswer(self, s, cmd):
  1361.         while 1:
  1362.             if s.rawData():
  1363.                 if s.get_command() == cmd:
  1364.                     if s.get_error_class() == 0x00 and s.get_error_code() == 0x00:
  1365.                         return 1
  1366.                     else:
  1367.                         raise SessionError, ( "SMB Library Error", s.get_error_class(), s.get_error_code())
  1368.                 else:
  1369.                     break
  1370. #                    raise SessionError("Invalid command received. %x" % cmd)
  1371. #            s=self.recv_packet(None)   
  1372.         return 0
  1373.     
  1374.     def __neg_session(self):
  1375.         s = SMBPacket()
  1376.         s.set_command(SMB.SMB_COM_NEGOTIATE)
  1377.         s.set_buffer('\x02NT LM 0.12\x00')
  1378.         self.send_smb(s)
  1379.  
  1380.         while 1:
  1381.             s = self.recv_packet()
  1382.             if self.isValidAnswer(s,SMB.SMB_COM_NEGOTIATE):
  1383.                 self.__ntlm_dialect = NTLMDialect(s.rawData())
  1384.                 if self.__ntlm_dialect.get_selected_dialect() == 0xffff:
  1385.                     raise UnsupportedFeature,"Remote server does not know NT LM 0.12"
  1386.  
  1387.                 #NL LM 0.12 dialect selected
  1388.                 if self.__ntlm_dialect.get_lsw_capabilities() & SMB.CAP_EXTENDED_SECURITY:
  1389.                     raise UnsupportedFeature, "This version of pysmb does not support extended security validation. Please file a request for it."
  1390.  
  1391.                 self.__is_pathcaseless = s.get_flags() & SMB.FLAGS1_PATHCASELESS
  1392.  
  1393.                 return 1
  1394.             else:
  1395.                 return 0
  1396.  
  1397.  
  1398.     def tree_connect(self, path, password = '', service = SERVICE_ANY):
  1399.         # return 0x800
  1400.         if password:
  1401.             # Password is only encrypted if the server passed us an "encryption" during protocol dialect
  1402.             if self.__ntlm_dialect.get_encryption_key():
  1403.                 # this code is untested
  1404.                 password = self.get_ntlmv1_response(ntlm.compute_lmhash(password))
  1405.  
  1406.         if not unicode_support:
  1407.             if unicode_convert:
  1408.                 path = str(path)
  1409.             else:
  1410.                 raise Except('SMB: Can\t conver path from unicode!')
  1411.  
  1412.         smb = NewSMBPacket()
  1413.         smb['Flags1']  = 8
  1414.         
  1415.         treeConnect = SMBCommand(SMB.SMB_COM_TREE_CONNECT)
  1416.         treeConnect['Parameters'] = SMBTreeConnect_Parameters()
  1417.         treeConnect['Data']       = SMBTreeConnect_Data()
  1418.         treeConnect['Data']['Path'] = path.upper()
  1419.         treeConnect['Data']['Password'] = password
  1420.         treeConnect['Data']['Service'] = service
  1421.  
  1422.         smb.addCommand(treeConnect)
  1423.  
  1424.         self.sendSMB(smb)
  1425.  
  1426.         while 1:
  1427.             smb = self.recvSMB()
  1428.             if smb.isValidAnswer(SMB.SMB_COM_TREE_CONNECT):
  1429.                 # XXX Here we are ignoring the rest of the response
  1430.                 return smb['Tid']
  1431.             return smb['Tid']
  1432.  
  1433.     def tree_connect_andx(self, path, password = None, service = SERVICE_ANY):
  1434.         if password:
  1435.             # Password is only encrypted if the server passed us an "encryption" during protocol dialect
  1436.             if self.__ntlm_dialect.get_encryption_key():
  1437.                 # this code is untested
  1438.                 password = self.get_ntlmv1_response(ntlm.compute_lmhash(password))
  1439.         else:
  1440.             password = '\x00'
  1441.  
  1442.         if not unicode_support:
  1443.             if unicode_convert:
  1444.                 path = str(path)
  1445.             else:
  1446.                 raise Except('SMB: Can\t convert path from unicode!')
  1447.  
  1448.         smb = NewSMBPacket()
  1449.         smb['Flags1']  = 8
  1450.         
  1451.         treeConnect = SMBCommand(SMB.SMB_COM_TREE_CONNECT_ANDX)
  1452.         treeConnect['Parameters'] = SMBTreeConnectAndX_Parameters()
  1453.         treeConnect['Data']       = SMBTreeConnectAndX_Data()
  1454.         treeConnect['Parameters']['PasswordLength'] = len(password)
  1455.         treeConnect['Data']['Password'] = password
  1456.         treeConnect['Data']['Path'] = path.upper()
  1457.         treeConnect['Data']['Service'] = service
  1458.  
  1459.         smb.addCommand(treeConnect)
  1460.  
  1461.         # filename = "\PIPE\epmapper"
  1462.  
  1463.         # ntCreate = SMBCommand(SMB.SMB_COM_NT_CREATE_ANDX)
  1464.         # ntCreate['Parameters'] = SMBNtCreateAndX_Parameters()
  1465.         # ntCreate['Data']       = SMBNtCreateAndX_Data()
  1466.         # ntCreate['Parameters']['FileNameLength'] = len(filename)
  1467.         # ntCreate['Parameters']['CreateFlags'] = 0
  1468.         # ntCreate['Parameters']['AccessMask'] = 0x3
  1469.         # ntCreate['Parameters']['CreateOptions'] = 0x0
  1470.         # ntCreate['Data']['FileName'] = filename
  1471.  
  1472.         # smb.addCommand(ntCreate)
  1473.         self.sendSMB(smb)
  1474.  
  1475.         while 1:
  1476.             smb = self.recvSMB()
  1477.             if smb.isValidAnswer(SMB.SMB_COM_TREE_CONNECT_ANDX):
  1478.                 # XXX Here we are ignoring the rest of the response
  1479.                 return smb['Tid']
  1480.             return smb['Tid']
  1481.  
  1482.     # backwars compatibility
  1483.     connect_tree = tree_connect_andx
  1484.  
  1485.     def get_server_name(self):
  1486.         return self.__ntlm_dialect.get_server_name()
  1487.  
  1488.     def get_session_key(self):
  1489.         return self.__ntlm_dialect.get_session_key()
  1490.  
  1491.     def get_server_time(self):
  1492.         high, low = self.__ntlm_dialect.get_utc()
  1493.         min = self.__ntlm_dialect.get_minutes_utc()
  1494.         return samr.display_time(high, low, min)
  1495.  
  1496.     def disconnect_tree(self, tid):
  1497.         smb = NewSMBPacket()
  1498.         smb['Tid']  = tid
  1499.         smb.addCommand(SMBCommand(SMB.SMB_COM_TREE_DISCONNECT))
  1500.         self.sendSMB(smb)
  1501.  
  1502.         smb = self.recvSMB()
  1503.  
  1504.     def open(self, tid, filename, open_mode, desired_access):
  1505.         smb = NewSMBPacket()
  1506.         smb['Flags']  = 8
  1507.         smb['Flags2'] = SMB.FLAGS2_LONG_FILENAME
  1508.         smb['Tid']    = tid
  1509.  
  1510.         openFile = SMBCommand(SMB.SMB_COM_OPEN)
  1511.         openFile['Parameters'] = SMBOpen_Parameters()
  1512.         openFile['Parameters']['DesiredAccess']    = desired_access
  1513.         openFile['Parameters']['OpenMode']         = open_mode
  1514.         openFile['Parameters']['SearchAttributes'] = ATTR_READONLY | ATTR_HIDDEN | ATTR_ARCHIVE
  1515.         openFile['Data']       = SMBOpen_Data()
  1516.         openFile['Data']['FileName'] = filename
  1517.         
  1518.         smb.addCommand(openFile)
  1519.  
  1520.         self.sendSMB(smb)
  1521.         
  1522.         smb = self.recvSMB()
  1523.         if smb.isValidAnswer(SMB.SMB_COM_OPEN):
  1524.             # XXX Here we are ignoring the rest of the response
  1525.             openFileResponse   = SMBCommand(smb['Data'][0])
  1526.             openFileParameters = SMBOpenResponse_Parameters(openFileResponse['Parameters'])
  1527.  
  1528.             return (
  1529.                 openFileParameters['Fid'],
  1530.                 openFileParameters['FileAttributes'],
  1531.                 openFileParameters['LastWriten'],
  1532.                 openFileParameters['FileSize'],
  1533.                 openFileParameters['GrantedAccess'],
  1534.             )
  1535.         
  1536.     def open_andx(self, tid, filename, open_mode, desired_access):
  1537.         smb = NewSMBPacket()
  1538.         smb['Flags']  = 8
  1539.         smb['Flags2'] = SMB.FLAGS2_LONG_FILENAME
  1540.         smb['Tid']    = tid
  1541.  
  1542.         openFile = SMBCommand(SMB.SMB_COM_OPEN_ANDX)
  1543.         openFile['Parameters'] = SMBOpenAndX_Parameters()
  1544.         openFile['Parameters']['DesiredAccess']    = desired_access
  1545.         openFile['Parameters']['OpenMode']         = open_mode
  1546.         openFile['Parameters']['SearchAttributes'] = ATTR_READONLY | ATTR_HIDDEN | ATTR_ARCHIVE
  1547.         openFile['Data']       = SMBOpenAndX_Data()
  1548.         openFile['Data']['FileName'] = filename
  1549.         
  1550.         smb.addCommand(openFile)
  1551.  
  1552.         self.sendSMB(smb)
  1553.         
  1554.         smb = self.recvSMB()
  1555.         if smb.isValidAnswer(SMB.SMB_COM_OPEN_ANDX):
  1556.             # XXX Here we are ignoring the rest of the response
  1557.             openFileResponse   = SMBCommand(smb['Data'][0])
  1558.             openFileParameters = SMBOpenAndXResponse_Parameters(openFileResponse['Parameters'])
  1559.  
  1560.             return (
  1561.                 openFileParameters['Fid'],
  1562.                 openFileParameters['FileAttributes'],
  1563.                 openFileParameters['LastWriten'],
  1564.                 openFileParameters['FileSize'],
  1565.                 openFileParameters['GrantedAccess'],
  1566.                 openFileParameters['FileType'],
  1567.                 openFileParameters['IPCState'],
  1568.                 openFileParameters['Action'],
  1569.                 openFileParameters['ServerFid'],
  1570.             )
  1571.         
  1572.     def close(self, tid, fid):
  1573.         s = SMBPacket()
  1574.         s.set_command(SMB.SMB_COM_CLOSE)
  1575.         s.set_tid(tid)
  1576.         s.set_parameter_words(pack('<HL', fid, 0))
  1577.         self.send_smb(s)
  1578.         s = self.recv_packet()
  1579.  
  1580.     def send_trans(self, tid, setup, name, param, data, noAnswer = 0):
  1581.         t = TRANSHeader()
  1582.         s = SMBPacket()
  1583.         s.set_tid(tid)
  1584.         s.set_command(SMB.SMB_COM_TRANSACTION)
  1585.         s.set_flags(self.__is_pathcaseless)
  1586.         s.set_flags2(SMB.FLAGS2_LONG_FILENAME)
  1587.         t.set_setup(setup)
  1588.         t.set_name(name)
  1589.         t.set_parameters(param)
  1590.         t.set_data(data)
  1591.         t.set_max_param_count(1024) # Saca esto y se muere remotamente
  1592.         t.set_max_data_count(65504) # Saca esto y se muere remotamente
  1593.         if noAnswer:
  1594.             t.set_flags(TRANS_NO_RESPONSE)
  1595.         s.set_parameter_words(t.get_rawParameters())
  1596.         s.set_buffer(t.rawData())
  1597.         self.send_smb(s)
  1598.  
  1599.     def __trans(self, tid, setup, name, param, data):
  1600.         data_len = len(data)
  1601.         name_len = len(name)
  1602.         param_len = len(param)
  1603.         setup_len = len(setup)
  1604.  
  1605.         assert setup_len & 0x01 == 0
  1606.  
  1607.         param_offset = name_len + setup_len + 63
  1608.         data_offset = param_offset + param_len
  1609.             
  1610.         self.__send_smb_packet(SMB.SMB_COM_TRANSACTION, self.__is_pathcaseless, SMB.FLAGS2_LONG_FILENAME, tid, 0, pack('<HHHHBBHLHHHHHBB', param_len, data_len, 1024, 65504, 0, 0, 0, 0, 0, param_len, param_offset, data_len, data_offset, setup_len / 2, 0) + setup, name + param + data)
  1611.  
  1612.     def trans2(self, tid, setup, name, param, data):
  1613.         data_len = len(data)
  1614.         name_len = len(name)
  1615.         param_len = len(param)
  1616.         setup_len = len(setup)
  1617.  
  1618.         assert setup_len & 0x01 == 0
  1619.  
  1620.         param_offset = name_len + setup_len + 63
  1621.         data_offset = param_offset + param_len
  1622.             
  1623.         self.__send_smb_packet(SMB.SMB_COM_TRANSACTION2, self.__is_pathcaseless, SMB.FLAGS2_LONG_FILENAME, tid, 0, pack('<HHHHBBHLHHHHHBB', param_len, data_len, 1024, self.__ntlm_dialect.get_max_buffer(), 0, 0, 0, 0, 0, param_len, param_offset, data_len, data_offset, setup_len / 2, 0) + setup, name  + param + data)
  1624.  
  1625.     def query_file_info(self, tid, fid):
  1626.         self.trans2(tid, '\x07\x00', '\x00', pack('<HH', fid, 0x107), '')
  1627.  
  1628.         while 1:
  1629.             s = self.recv_packet()
  1630.             if self.isValidAnswer(s,SMB.SMB_COM_TRANSACTION2):
  1631.                 f1, f2 = unpack('<LL', s.get_buffer()[53:53+8])
  1632.                 return (f2 & 0xffffffffL) << 32 | f1
  1633.  
  1634.     def __nonraw_retr_file(self, tid, fid, offset, datasize, callback):
  1635.         max_buf_size = self.__ntlm_dialect.get_max_buffer() & ~0x3ff  # Read in multiple KB blocks
  1636.         read_offset = offset
  1637.         while read_offset < datasize:
  1638.             data = self.read_andx(tid, fid, read_offset, max_buf_size)
  1639.  
  1640.             callback(data)
  1641.             read_offset += len(data)
  1642.  
  1643.     def __raw_retr_file(self, tid, fid, offset, datasize, callback):
  1644.         max_buf_size = self.__ntlm_dialect.get_max_buffer() & ~0x3ff  # Write in multiple KB blocks
  1645.         read_offset = offset
  1646.         while read_offset < datasize:
  1647.             data = self.read_raw(tid, fid, read_offset, 0xffff)
  1648.             if not data:
  1649.                 # No data returned. Need to send SMB_COM_READ_ANDX to find out what is the error.
  1650.                 data = self.read_andx(tid, fid, read_offset, max_buf_size)
  1651.  
  1652.             callback(data)
  1653.             read_offset += len(data)
  1654.  
  1655.     def __nonraw_stor_file(self, tid, fid, offset, datasize, callback):
  1656.         max_buf_size = self.__ntlm_dialect.get_max_buffer() & ~0x3ff  # Write in multiple KB blocks
  1657.         write_offset = offset
  1658.         while 1:
  1659.             data = callback(max_buf_size)
  1660.             if not data:
  1661.                 break
  1662.             
  1663.             self.__send_smb_packet(SMB.SMB_COM_WRITE_ANDX, 0, 0, tid, 0, pack('<BBHHLLHHHHH', 0xff, 0, 0, fid, write_offset, 0, 0, 0, 0, len(data), 59), data)
  1664.             
  1665.             while 1:
  1666.                 s = self.recv_packet()
  1667.                 if self.isValidAnswer(s,SMB.SMB_COM_WRITE_ANDX):
  1668.                     offset = unpack('<H', s.get_parameter_words()[2:4])[0]
  1669.                     write_offset = write_offset + unpack('<H', s.get_parameter_words()[4:6])[0]
  1670.                     break
  1671.  
  1672.     def __raw_stor_file(self, tid, fid, offset, datasize, callback):
  1673.         write_offset = offset
  1674.         while 1:
  1675.             read_data = callback(65535)
  1676.             if not read_data:
  1677.                 break
  1678.             read_len = len(read_data)
  1679.             self.__send_smb_packet(SMB.SMB_COM_WRITE_RAW, 0, 0, tid, 0, pack('<HHHLLHLHH', fid, read_len, 0, write_offset, 0, 0, 0, 0, 59), '')
  1680.             while 1:
  1681.                 s = self.recv_packet()
  1682.                 if self.isValidAnswer(s,SMB.SMB_COM_WRITE_RAW):
  1683.                     self.__sess.send_packet(read_data)
  1684.                     write_offset = write_offset + read_len
  1685.                     break
  1686.  
  1687.         # We need to close fid to check whether the last raw packet is written successfully
  1688.         self.__send_smb_packet(SMB.SMB_COM_CLOSE, 0, 0, tid, 0, pack('<HL', fid, 0), '')
  1689.         while 1:
  1690.             s = self.recv_packet()
  1691.             if self.isValidAnswer(s,SMB.SMB_COM_CLOSE):
  1692.                 if s.get_error_class() == 0x00 and s.get_error_code() == 0x00:
  1693.                     return
  1694.  
  1695.     def __browse_servers(self, server_flags, container_type, domain):
  1696.         tid = self.tree_connect_andx('\\\\' + self.__remote_name + '\\IPC$')
  1697.  
  1698.         buf = StringIO()
  1699.         try:
  1700.             if server_flags & 0x80000000:
  1701.                 self.__trans(tid, '', '\\PIPE\\LANMAN\x00', '\x68\x00WrLehDz\x00' + 'B16BBDz\x00\x01\x00\xff\xff\x00\x00\x00\x80', '')
  1702.             else:
  1703.                 self.__trans(tid, '', '\\PIPE\\LANMAN\x00', '\x68\x00WrLehDz\x00' + 'B16BBDz\x00\x01\x00\xff\xff' + pack('<l', server_flags)  + domain + '\x00', '')
  1704.                 
  1705.             servers = [ ]
  1706.             entry_count = 0
  1707.             while 1:
  1708.                 s = self.recv_packet()
  1709.                 if self.isValidAnswer(s,SMB.SMB_COM_TRANSACTION):
  1710.                     has_more, _, transparam, transdata = self.__decode_trans(s.get_parameter_words(), s.get_buffer())
  1711.                     if not entry_count:
  1712.                         status, convert, entry_count, avail_entry = unpack('<HHHH', transparam[:8])
  1713.                         if status and status != 234:  # status 234 means have more data
  1714.                             raise SessionError, ( 'Browse domains failed. (ErrClass: %d and ErrCode: %d)' % ( 0x80, status ), 0x80, status )
  1715.                     buf.write(transdata)
  1716.  
  1717.                     if not has_more:
  1718.                         server_data = buf.getvalue()
  1719.  
  1720.                         for i in range(0, entry_count):
  1721.                             server, _, server_type, comment_offset = unpack('<16s2sll', server_data[i * 26:i * 26 + 26])
  1722.                             idx = string.find(server, '\0')
  1723.                             idx2 = string.find(server_data, '\0', comment_offset)
  1724.                             if idx < 0:
  1725.                                 server = server[:idx]
  1726.                             servers.append(container_type(server, server_type, server_data[comment_offset:idx2]))
  1727.                         return servers
  1728.         finally:
  1729.             buf.close()
  1730.             self.disconnect_tree(tid)            
  1731.  
  1732.     def get_server_domain(self):
  1733.         return self.__server_domain
  1734.  
  1735.     def get_server_os(self):
  1736.         return self.__server_os
  1737.  
  1738.     def get_server_lanman(self):
  1739.         return self.__server_lanman
  1740.  
  1741.     def is_login_required(self):
  1742.         # Login is required if share mode is user. Otherwise only public services or services in share mode
  1743.         # are allowed.
  1744.         return self.__ntlm_dialect.is_share_mode() == SMB.SECURITY_SHARE_USER
  1745.  
  1746.     def get_ntlmv1_response(self, key):
  1747.         challenge = self.__ntlm_dialect.get_encryption_key()
  1748.         return ntlm.get_ntlmv1_response(key, challenge)
  1749.  
  1750.     def hmac_md5(self, key, data):
  1751.         import POW
  1752.         h = POW.Hmac(POW.MD5_DIGEST, key)
  1753.         h.update(data)
  1754.         result = h.mac()
  1755.         return result
  1756.  
  1757.     def get_ntlmv2_response(self, hash):
  1758.         """
  1759.         blob = RandomBytes( blobsize );
  1760.         data = concat( ServerChallenge, 8, blob, blobsize );
  1761.         hmac = hmac_md5( v2hash, 16, data, (8 + blobsize) );
  1762.         v2resp = concat( hmac, 16, blob, blobsize );
  1763.         """
  1764.         return ''
  1765.  
  1766.     def login(self, user, password, domain = '', lmhash = '', nthash = ''):
  1767.         if password != '' or (password == '' and lmhash == '' and nthash == ''):
  1768.             self.login_plaintext_password(user, password)
  1769.         elif lmhash != '' or nthash != '':
  1770.             self.login_pass_the_hash(user, lmhash, nthash, domain)
  1771.  
  1772.     def _login(self, user, pwd_ansi, pwd_unicode, domain = ''):
  1773.         smb = NewSMBPacket()
  1774.         smb['Flags1']  = 8
  1775.         
  1776.         sessionSetup = SMBCommand(SMB.SMB_COM_SESSION_SETUP_ANDX)
  1777.         sessionSetup['Parameters'] = SMBSessionSetupAndX_Parameters()
  1778.         sessionSetup['Data']       = SMBSessionSetupAndX_Data()
  1779.  
  1780.         sessionSetup['Parameters']['MaxBuffer']        = 65535
  1781.         sessionSetup['Parameters']['MaxMpxCount']      = 2
  1782.         sessionSetup['Parameters']['VCNumber']         = os.getpid()
  1783.         sessionSetup['Parameters']['SessionKey']       = self.__ntlm_dialect.get_session_key()
  1784.         sessionSetup['Parameters']['AnsiPwdLength']    = len(pwd_ansi)
  1785.         sessionSetup['Parameters']['UnicodePwdLength'] = len(pwd_unicode)
  1786.         sessionSetup['Parameters']['Capabilities']     = SMB.CAP_RAW_MODE
  1787.  
  1788.         sessionSetup['Data']['AnsiPwd']       = pwd_ansi
  1789.         sessionSetup['Data']['UnicodePwd']    = pwd_unicode
  1790.         sessionSetup['Data']['Account']       = str(user)
  1791.         sessionSetup['Data']['PrimaryDomain'] = str(domain)
  1792.         sessionSetup['Data']['NativeOS']      = str(os.name)
  1793.         sessionSetup['Data']['NativeLanMan']  = 'pysmb'
  1794.  
  1795.         smb.addCommand(sessionSetup)
  1796.  
  1797.         self.sendSMB(smb)
  1798.  
  1799.         smb = self.recvSMB()
  1800.         if smb.isValidAnswer(SMB.SMB_COM_SESSION_SETUP_ANDX):
  1801.             # We will need to use this uid field for all future requests/responses
  1802.             self.__uid = smb['Uid']
  1803.             sessionResponse   = SMBCommand(smb['Data'][0])
  1804.             sessionParameters = SMBSessionSetupAndXResponse_Parameters(sessionResponse['Parameters'])
  1805.             sessionData       = SMBSessionSetupAndXResponse_Data(flags = smb['Flags2'], data = sessionResponse['Data'])
  1806.  
  1807.             self.__server_os     = sessionData['NativeOS']
  1808.             self.__server_lanman = sessionData['NativeLanMan']
  1809.             self.__server_domain = sessionData['PrimaryDomain']
  1810.  
  1811.             return 1
  1812.         else: raise Exception('Error: Could not login successfully')
  1813.  
  1814.     def read(self, tid, fid, offset=0, max_size = None, wait_answer=1):
  1815.         if not max_size:
  1816.             max_size = self.__ntlm_dialect.get_max_buffer() # Read in multiple KB blocks
  1817.         
  1818.         # max_size is not working, because although it would, the server returns an error (More data avail)
  1819.  
  1820.         smb = NewSMBPacket()
  1821.         smb['Flags1'] = 0x18
  1822.         smb['Flags2'] = 0
  1823.         smb['Tid']    = tid
  1824.  
  1825.         read = SMBCommand(SMB.SMB_COM_READ)
  1826.         
  1827.         read['Parameters'] = SMBRead_Parameters()
  1828.         read['Parameters']['Fid'] = fid
  1829.         read['Parameters']['Offset'] = offset
  1830.         read['Parameters']['Count'] = max_size
  1831.  
  1832.         smb.addCommand(read)
  1833.  
  1834.         if wait_answer:
  1835.             answer = ''
  1836.             while 1:
  1837.                 self.sendSMB(smb)
  1838.                 ans = self.recvSMB()
  1839.  
  1840.                 if ans.isValidAnswer(SMB.SMB_COM_READ):
  1841.                     readResponse   = SMBCommand(ans['Data'][0])
  1842.                     readParameters = SMBReadResponse_Parameters(readResponse['Parameters'])
  1843.                     readData       = SMBReadResponse_Data(readResponse['Data'])
  1844.  
  1845.                     return readData['Data']
  1846.  
  1847.         return None
  1848.  
  1849.     def read_andx(self, tid, fid, offset=0, max_size = None, wait_answer=1):
  1850.         if not max_size:
  1851.             max_size = self.__ntlm_dialect.get_max_buffer() # Read in multiple KB blocks
  1852.         
  1853.         # max_size is not working, because although it would, the server returns an error (More data avail)
  1854.  
  1855.         smb = NewSMBPacket()
  1856.         smb['Flags1'] = 0x18
  1857.         smb['Flags2'] = 0
  1858.         smb['Tid']    = tid
  1859.  
  1860.         readAndX = SMBCommand(SMB.SMB_COM_READ_ANDX)
  1861.         
  1862.         readAndX['Parameters'] = SMBReadAndX_Parameters()
  1863.         readAndX['Parameters']['Fid'] = fid
  1864.         readAndX['Parameters']['Offset'] = offset
  1865.         readAndX['Parameters']['MaxCount'] = max_size
  1866.  
  1867.         smb.addCommand(readAndX)
  1868.  
  1869.         if wait_answer:
  1870.             answer = ''
  1871.             while 1:
  1872.                 self.sendSMB(smb)
  1873.                 ans = self.recvSMB()
  1874.  
  1875.                 if ans.isValidAnswer(SMB.SMB_COM_READ_ANDX):
  1876.                     # XXX Here we are only using a few fields from the response
  1877.                     readAndXResponse   = SMBCommand(ans['Data'][0])
  1878.                     readAndXParameters = SMBReadAndXResponse_Parameters(readAndXResponse['Parameters'])
  1879.  
  1880.                     offset = readAndXParameters['DataOffset']
  1881.                     count = readAndXParameters['DataCount']+0x10000*readAndXParameters['DataCount_Hi']
  1882.                     answer += str(ans)[offset:offset+count]
  1883.                     if not ans.isMoreData():
  1884.                         return answer
  1885.                     max_size = min(max_size, readAndXParameters['Remaining'])
  1886.                     readAndX['Parameters']['Offset'] += count                      # XXX Offset is not important (apparently)
  1887.  
  1888.         return None
  1889.  
  1890.     def read_raw(self, tid, fid, offset=0, max_size = None, wait_answer=1):
  1891.         if not max_size:
  1892.             max_size = self.__ntlm_dialect.get_max_buffer() # Read in multiple KB blocks
  1893.         
  1894.         # max_size is not working, because although it would, the server returns an error (More data avail)
  1895.  
  1896.         smb = NewSMBPacket()
  1897.         smb['Flags1'] = 0x18
  1898.         smb['Flags2'] = 0
  1899.         smb['Tid']    = tid
  1900.  
  1901.         readRaw = SMBCommand(SMB.SMB_COM_READ_RAW)
  1902.         
  1903.         readRaw['Parameters'] = SMBReadRaw_Parameters()
  1904.         readRaw['Parameters']['Fid'] = fid
  1905.         readRaw['Parameters']['Offset'] = offset
  1906.         readRaw['Parameters']['MaxCount'] = max_size
  1907.  
  1908.         smb.addCommand(readRaw)
  1909.  
  1910.         self.sendSMB(smb)
  1911.         if wait_answer:
  1912.             data = self.__sess.recv_packet(self.__timeout).get_trailer()
  1913.             if not data:
  1914.                 # If there is no data it means there was an error
  1915.                 data = self.read_andx(tid, fid, offset, max_size)
  1916.             return data
  1917.  
  1918.         return None
  1919.  
  1920.     def write(self,tid,fid,data, offset = 0, wait_answer=1):
  1921.         smb = NewSMBPacket()
  1922.         smb['Flags1'] = 0x18
  1923.         smb['Flags2'] = 0
  1924.         smb['Tid']    = tid
  1925.  
  1926.         write = SMBCommand(SMB.SMB_COM_WRITE)
  1927.         smb.addCommand(write)
  1928.         
  1929.         write['Parameters'] = SMBWrite_Parameters()
  1930.         write['Data'] = SMBWrite_Data()
  1931.         write['Parameters']['Fid'] = fid
  1932.         write['Parameters']['Count'] = len(data)
  1933.         write['Parameters']['Offset'] = offset
  1934.         write['Parameters']['Remaining'] = len(data)
  1935.         write['Data']['Data'] = data
  1936.  
  1937.         self.sendSMB(smb)
  1938.                 
  1939.         if wait_answer:
  1940.             smb = self.recvSMB()
  1941.             if smb.isValidAnswer(SMB.SMB_COM_WRITE):
  1942.                 return smb
  1943.         return None
  1944.  
  1945.     def write_andx(self,tid,fid,data, offset = 0, wait_answer=1):
  1946.         smb = NewSMBPacket()
  1947.         smb['Flags1'] = 0x18
  1948.         smb['Flags2'] = 0
  1949.         smb['Tid']    = tid
  1950.  
  1951.         writeAndX = SMBCommand(SMB.SMB_COM_WRITE_ANDX)
  1952.         smb.addCommand(writeAndX)
  1953.         
  1954.         writeAndX['Parameters'] = SMBWriteAndX_Parameters()
  1955.         writeAndX['Parameters']['Fid'] = fid
  1956.         writeAndX['Parameters']['Offset'] = offset
  1957.         writeAndX['Parameters']['WriteMode'] = 8
  1958.         writeAndX['Parameters']['Remaining'] = len(data)
  1959.         writeAndX['Parameters']['DataLength'] = len(data)
  1960.         writeAndX['Parameters']['DataOffset'] = len(smb)    # this length already includes the parameter
  1961.         writeAndX['Data'] = data
  1962.  
  1963.         self.sendSMB(smb)
  1964.                 
  1965.         if wait_answer:
  1966.             smb = self.recvSMB()
  1967.             if smb.isValidAnswer(SMB.SMB_COM_WRITE_ANDX):
  1968.                 return smb
  1969.         return None
  1970.  
  1971.     def write_raw(self,tid,fid,data, offset = 0, wait_answer=1):
  1972.         smb = NewSMBPacket()
  1973.         smb['Flags1'] = 0x18
  1974.         smb['Flags2'] = 0
  1975.         smb['Tid']    = tid
  1976.  
  1977.         writeRaw = SMBCommand(SMB.SMB_COM_WRITE_RAW)
  1978.         smb.addCommand(writeRaw)
  1979.         
  1980.         writeRaw['Parameters'] = SMBWriteRaw_Parameters()
  1981.         writeRaw['Parameters']['Fid'] = fid
  1982.         writeRaw['Parameters']['Offset'] = offset
  1983.         writeRaw['Parameters']['Count'] = len(data)
  1984.         writeRaw['Parameters']['DataLength'] = 0
  1985.         writeRaw['Parameters']['DataOffset'] = 0
  1986.  
  1987.         self.sendSMB(smb)
  1988.         self.__sess.send_packet(data)
  1989.                 
  1990.         if wait_answer:
  1991.             smb = self.recvSMB()
  1992.             if smb.isValidAnswer(SMB.SMB_COM_WRITE_RAW):
  1993.                 return smb
  1994.         return None
  1995.  
  1996.     def TransactNamedPipe(self, tid, fid, data = '', noAnswer = 0, waitAnswer = 1, offset = 0):
  1997.         self.send_trans(tid,pack('<HH', 0x26, fid),'\\PIPE\\\x00','',data, noAnswer = noAnswer)
  1998.  
  1999.         if noAnswer or not waitAnswer:
  2000.             return
  2001.  
  2002.         s = self.recv_packet()
  2003.         if self.isValidAnswer(s,SMB.SMB_COM_TRANSACTION):
  2004.             trans = TRANSHeader(s.get_parameter_words(), s.get_buffer())
  2005.             return trans.get_data()
  2006.  
  2007.         return None
  2008.  
  2009.         
  2010.  
  2011.     def nt_create_andx(self,tid,filename):
  2012.         smb = NewSMBPacket()
  2013.         smb['Flags1'] = 0x18
  2014.         smb['Flags2'] = SMB.FLAGS2_LONG_FILENAME
  2015.         smb['Tid']    = tid
  2016.         
  2017.         ntCreate = SMBCommand(SMB.SMB_COM_NT_CREATE_ANDX)
  2018.         ntCreate['Parameters'] = SMBNtCreateAndX_Parameters()
  2019.         ntCreate['Data']       = SMBNtCreateAndX_Data()
  2020.         ntCreate['Parameters']['FileNameLength'] = len(filename)
  2021.         ntCreate['Parameters']['CreateFlags'] = 0x16
  2022.         ntCreate['Parameters']['AccessMask'] = 0x2019f
  2023.         ntCreate['Parameters']['CreateOptions'] = 0x40
  2024.  
  2025.         ntCreate['Data']['FileName'] = filename
  2026.  
  2027.         smb.addCommand(ntCreate)
  2028.  
  2029.         self.sendSMB(smb)
  2030.  
  2031.         while 1:
  2032.             smb = self.recvSMB()
  2033.             if smb.isValidAnswer(SMB.SMB_COM_NT_CREATE_ANDX):
  2034.                 # XXX Here we are ignoring the rest of the response
  2035.                 ntCreateResponse   = SMBCommand(smb['Data'][0])
  2036.                 ntCreateParameters = SMBNtCreateAndXResponse_Parameters(ntCreateResponse['Parameters'])
  2037.  
  2038.                 return ntCreateParameters['Fid']
  2039.  
  2040.     def login_pass_the_hash(self, user, lmhash, nthash, domain = ''):
  2041.         if len(lmhash) % 2:     lmhash = '0%s' % lmhash
  2042.         if len(nthash) % 2:     nthash = '0%s' % nthash
  2043.  
  2044.         if lmhash: lmhash = self.get_ntlmv1_response(a2b_hex(lmhash))
  2045.         if nthash: nthash = self.get_ntlmv1_response(a2b_hex(nthash))
  2046.  
  2047.         self._login(user, lmhash, nthash, domain)
  2048.  
  2049.     def login_plaintext_password(self, name, password, domain = ''):
  2050.         # Password is only encrypted if the server passed us an "encryption key" during protocol dialect negotiation
  2051.         if password and self.__ntlm_dialect.get_encryption_key():
  2052.             lmhash = ntlm.compute_lmhash(password)
  2053.             nthash = ntlm.compute_nthash(password)
  2054.             lmhash = self.get_ntlmv1_response(lmhash)
  2055.             nthash = self.get_ntlmv1_response(nthash)
  2056.         else:
  2057.             lmhash = password
  2058.             nthash = ''
  2059.         self._login(name, lmhash, nthash, domain)
  2060.  
  2061.     def logoff(self):
  2062.         s = SMBPacket()
  2063.         s.set_command(SMB.SMB_COM_LOGOFF_ANDX)
  2064.         s.set_parameter_words('\xff\x00\x00\x00')
  2065.         self.send_smb(s)
  2066.         s = self.recv_packet()
  2067.  
  2068.     def list_shared(self):
  2069.         tid = self.tree_connect_andx('\\\\' + self.__remote_name + '\\IPC$')
  2070.  
  2071.         buf = StringIO()
  2072.         try:
  2073.             self.send_trans(tid, '', '\\PIPE\\LANMAN\0', '\x00\x00WrLeh\0B13BWz\0\x01\x00\xe0\xff', '')
  2074.             numentries = 0
  2075.             share_list = [ ]
  2076.             while 1:
  2077.                 s = self.recv_packet()
  2078.                 if self.isValidAnswer(s,SMB.SMB_COM_TRANSACTION):
  2079.                     has_more, _, transparam, transdata = self.__decode_trans(s.get_parameter_words(), s.get_buffer())
  2080.                     if not numentries:
  2081.                         status, data_offset, numentries = unpack('<HHH', transparam[:6])
  2082.                     buf.write(transdata)
  2083.  
  2084.                     if not has_more:
  2085.                         share_data = buf.getvalue()
  2086.                         offset = 0
  2087.                         for i in range(0, numentries):
  2088.                             name = share_data[offset:string.find(share_data, '\0', offset)]
  2089.                             type, commentoffset = unpack('<HH', share_data[offset + 14:offset + 18])
  2090.                             comment = share_data[commentoffset-data_offset:share_data.find('\0', commentoffset-data_offset)]
  2091.                             offset = offset + 20
  2092.                             share_list.append(SharedDevice(name, type, comment))
  2093.                         return share_list
  2094.         finally:
  2095.             buf.close()
  2096.             self.disconnect_tree(tid)
  2097.  
  2098.     def list_path(self, service, path = '*', password = None):
  2099.         path = string.replace(path, '/', '\\')
  2100.  
  2101.         tid = self.tree_connect_andx('\\\\' + self.__remote_name + '\\' + service, password)
  2102.         try:
  2103.             self.trans2(tid, '\x01\x00', '\x00', '\x16\x00\x00\x02\x06\x00\x04\x01\x00\x00\x00\x00' + path + '\x00', '')
  2104.  
  2105.             while 1:
  2106.                 s = self.recv_packet()
  2107.                 if self.isValidAnswer(s,SMB.SMB_COM_TRANSACTION2):
  2108.                     has_more, _, transparam, transdata = self.__decode_trans(s.get_parameter_words(), s.get_buffer())
  2109.                     sid, searchcnt, eos, erroffset, lastnameoffset = unpack('<HHHHH', transparam)
  2110.                     files = [ ]
  2111.                     offset = 0
  2112.                     data_len = len(transdata)
  2113.                     while offset < data_len:
  2114.                         nextentry, fileindex, lowct, highct, lowat, highat, lowmt, highmt, lowcht, hightcht, loweof, higheof, lowsz, highsz, attrib, longnamelen, easz, shortnamelen = unpack('<lL12LLlLB', transdata[offset:offset + 69])
  2115.                         files.append(SharedFile(highct << 32 | lowct, highat << 32 | lowat, highmt << 32 | lowmt, higheof << 32 | loweof, highsz << 32 | lowsz, attrib, transdata[offset + 70:offset + 70 + shortnamelen], transdata[offset + 94:offset + 94 + longnamelen]))
  2116.                         offset = offset + nextentry
  2117.                         if not nextentry:
  2118.                             break
  2119.                     return files
  2120.         finally:
  2121.             self.disconnect_tree(tid)
  2122.  
  2123.     def retr_file(self, service, filename, callback, mode = SMB_O_OPEN, offset = 0, password = None):
  2124.         filename = string.replace(filename, '/', '\\')
  2125.  
  2126.         fid = -1
  2127.         tid = self.tree_connect_andx('\\\\' + self.__remote_name + '\\' + service, password)
  2128.         try:
  2129.             fid, attrib, lastwritetime, datasize, grantedaccess, filetype, devicestate, action, serverfid = self.open_andx(tid, filename, mode, SMB_ACCESS_READ | SMB_SHARE_DENY_WRITE)
  2130.  
  2131.             if not datasize:
  2132.                 datasize = self.query_file_info(tid, fid)
  2133.  
  2134.             if self.__ntlm_dialect.is_rawmode():
  2135.                 self.__raw_retr_file(tid, fid, offset, datasize, callback)
  2136.             else:
  2137.                 self.__nonraw_retr_file(tid, fid, offset, datasize, callback)
  2138.         finally:
  2139.             if fid >= 0:
  2140.                 self.close(tid, fid)
  2141.             self.disconnect_tree(tid)
  2142.  
  2143.     def stor_file(self, service, filename, callback, mode = SMB_O_CREAT | SMB_O_TRUNC, offset = 0, password = None):
  2144.         filename = string.replace(filename, '/', '\\')
  2145.  
  2146.         fid = -1
  2147.         tid = self.tree_connect_andx('\\\\' + self.__remote_name + '\\' + service, password)
  2148.         try:
  2149.             fid, attrib, lastwritetime, datasize, grantedaccess, filetype, devicestate, action, serverfid = self.open_andx(tid, filename, mode, SMB_ACCESS_WRITE | SMB_SHARE_DENY_WRITE)
  2150.  
  2151.             # If the max_transmit buffer size is more than 16KB, upload process using non-raw mode is actually
  2152.             # faster than using raw-mode.
  2153.             if self.__ntlm_dialect.get_max_buffer() < 16384 and self.__ntlm_dialect.is_rawmode():
  2154.                 # Once the __raw_stor_file returns, fid is already closed
  2155.                 self.__raw_stor_file(tid, fid, offset, datasize, callback)
  2156.                 fid = -1
  2157.             else:
  2158.                 self.__nonraw_stor_file(tid, fid, offset, datasize, callback)
  2159.         finally:
  2160.             if fid >= 0:
  2161.                 self.close(tid, fid)
  2162.             self.disconnect_tree(tid)
  2163.  
  2164.     def copy(self, src_service, src_path, dest_service, dest_path, callback = None, write_mode = SMB_O_CREAT | SMB_O_TRUNC, src_password = None, dest_password = None):
  2165.         dest_path = string.replace(dest_path, '/', '\\')
  2166.         src_path = string.replace(src_path, '/', '\\')
  2167.         src_tid = self.tree_connect_andx('\\\\' + self.__remote_name + '\\' + src_service, src_password)
  2168.  
  2169.         dest_tid = -1
  2170.         try:
  2171.             if src_service == dest_service:
  2172.                 dest_tid = src_tid
  2173.             else:
  2174.                 dest_tid = self.tree_connect_andx('\\\\' + self.__remote_name + '\\' + dest_service, dest_password)
  2175.             
  2176.             dest_fid = self.open_andx(dest_tid, dest_path, write_mode, SMB_ACCESS_WRITE | SMB_SHARE_DENY_WRITE)[0]
  2177.             src_fid, _, _, src_datasize, _, _, _, _, _ = self.open_andx(src_tid, src_path, SMB_O_OPEN, SMB_ACCESS_READ | SMB_SHARE_DENY_WRITE)
  2178.  
  2179.             if callback:
  2180.                 callback(0, src_datasize)
  2181.  
  2182.             max_buf_size = (self.__ntlm_dialect.get_max_buffer() >> 10) << 10
  2183.             read_offset = 0
  2184.             write_offset = 0
  2185.             while read_offset < src_datasize:
  2186.                 self.__send_smb_packet(SMB.SMB_COM_READ_ANDX, 0, 0, src_tid, 0, pack('<BBHHLHHLH', 0xff, 0, 0, src_fid, read_offset, max_buf_size, max_buf_size, 0, 0), '')
  2187.                 while 1:
  2188.                     s = self.recv_packet()
  2189.                     if self.isValidAnswer(s,SMB.SMB_COM_READ_ANDX):
  2190.                         offset = unpack('<H', s.get_parameter_words()[2:4])[0]
  2191.                         data_len, dataoffset = unpack('<HH', s.get_parameter_words()[10+offset:14+offset])
  2192.                         if data_len == len(d):
  2193.                             self.__send_smb_packet(SMB.SMB_COM_WRITE_ANDX, 0, 0, dest_tid, 0, pack('<BBHHLLHHHHH', 0xff, 0, 0, dest_fid, write_offset, 0, 0, 0, 0, data_len, 59), d)
  2194.                         else:
  2195.                             self.__send_smb_packet(SMB.SMB_COM_WRITE_ANDX, 0, 0, dest_tid, 0, pack('<BBHHLLHHHHH', 0xff, 0, 0, dest_fid, write_offset, 0, 0, 0, 0, data_len, 59), d[dataoffset - 59:dataoffset - 59 + data_len])
  2196.                         while 1:
  2197.                             s = self.recv_packet()
  2198.                             if self.isValidAnswer(s,SMB.SMB_COM_WRITE_ANDX):
  2199.                                 offset = unpack('<H', s.get_parameter_words()[2:4])[0]
  2200.                                 write_offset = write_offset + unpack('<H', s.get_parameter_words()[4+offset:6+offset])[0]
  2201.                                 break
  2202.                         read_offset = read_offset + data_len
  2203.                         if callback:
  2204.                             callback(read_offset, src_datasize)
  2205.                         break
  2206.                 
  2207.         finally:
  2208.             self.disconnect_tree(src_tid)
  2209.             if dest_tid > -1 and src_service != dest_service:
  2210.                 self.disconnect_tree(dest_tid)
  2211.  
  2212.     def check_dir(self, service, path, password = None):
  2213.         tid = self.tree_connect_andx('\\\\' + self.__remote_name + '\\' + service, password)
  2214.         try:
  2215.             self.__send_smb_packet(SMB.SMB_COM_CHECK_DIRECTORY, 0x08, 0, tid, 0, '', '\x04' + path + '\x00')
  2216.  
  2217.             while 1:
  2218.                 s = self.recv_packet()
  2219.                 if self.isValidAnswer(s,SMB.SMB_COM_CHECK_DIRECTORY):
  2220.                     return
  2221.         finally:
  2222.             self.disconnect_tree(s.get_tid())
  2223.  
  2224.     def remove(self, service, path, password = None):
  2225.         # Perform a list to ensure the path exists
  2226.         self.list_path(service, path, password)
  2227.  
  2228.         tid = self.tree_connect_andx('\\\\' + self.__remote_name + '\\' + service, password)
  2229.         try:
  2230.             self.__send_smb_packet(SMB.SMB_COM_DELETE, 0x08, 0, tid, 0, pack('<H', ATTR_HIDDEN | ATTR_SYSTEM | ATTR_ARCHIVE), '\x04' + path + '\x00')
  2231.  
  2232.             while 1:
  2233.                 s = self.recv_packet()
  2234.                 if self.isValidAnswer(s,SMB.SMB_COM_DELETE):
  2235.                     return
  2236.         finally:
  2237.             self.disconnect_tree(s.get_tid())
  2238.  
  2239.     def rmdir(self, service, path, password = None):
  2240.         # Check that the directory exists
  2241.         self.check_dir(service, path, password)
  2242.  
  2243.         tid = self.tree_connect_andx('\\\\' + self.__remote_name + '\\' + service, password)
  2244.         try:
  2245.             self.__send_smb_packet(SMB.SMB_COM_DELETE_DIRECTORY, 0x08, 0, tid, 0, '', '\x04' + path + '\x00')
  2246.  
  2247.             while 1:
  2248.                 s = self.recv_packet()
  2249.                 if self.isValidAnswer(s,SMB.SMB_COM_DELETE_DIRECTORY):
  2250.                     return
  2251.         finally:
  2252.             self.disconnect_tree(s.get_tid())
  2253.  
  2254.     def mkdir(self, service, path, password = None):
  2255.         tid = self.tree_connect_andx('\\\\' + self.__remote_name + '\\' + service, password)
  2256.         try:
  2257.             s = SMBPacket()
  2258.             s.set_command(SMB.SMB_COM_CREATE_DIRECTORY)
  2259.             s.set_flags(0x08)
  2260.             s.set_flags2(0)
  2261.             s.set_tid(tid)
  2262.             s.set_parameter_words('') # check this! don't know if i don'thave to put this
  2263.             s.set_buffer('\x04' + path + '\x00')
  2264.             self.send_smb(s)
  2265.             s = self.recv_packet()
  2266.             if self.isValidAnswer(s,SMB.SMB_COM_CREATE_DIRECTORY):
  2267.                 return 1
  2268.             return 0
  2269.         finally:
  2270.             self.disconnect_tree(s.get_tid())
  2271.  
  2272.     def rename(self, service, old_path, new_path, password = None):
  2273.         tid = self.tree_connect_andx('\\\\' + self.__remote_name + '\\' + service, password)
  2274.         try:
  2275.             s = SMBPacket()
  2276.             s.set_command(SMB.SMB_COM_RENAME)
  2277.             s.set_flags(0x08)
  2278.             s.set_flags2(0)
  2279.             s.set_tid(tid)
  2280.             s.set_parameter_words(pack('<H', ATTR_SYSTEM | ATTR_HIDDEN | ATTR_DIRECTORY))
  2281.             s.set_buffer('\x04' + old_path + '\x00\x04' + new_path + '\x00')
  2282.             self.send_smb(s)
  2283.             s = self.recv_packet()
  2284.             if self.isValidAnswer(s,SMB.SMB_COM_RENAME):
  2285.                 return 1
  2286.             return 0
  2287.         finally:
  2288.             self.disconnect_tree(s.get_tid())
  2289.  
  2290.     def browse_domains(self):
  2291.         return self.__browse_servers(SV_TYPE_DOMAIN_ENUM, SMBDomain, '')
  2292.  
  2293.     def browse_servers_for_domain(self, domain = None):
  2294.         if not domain:
  2295.             domain = self.__server_domain
  2296.  
  2297.         return self.__browse_servers(SV_TYPE_SERVER | SV_TYPE_PRINTQ_SERVER | SV_TYPE_WFW | SV_TYPE_NT, SMBMachine, domain)
  2298.  
  2299.     def get_socket(self):
  2300.         return self.__sess.get_socket()
  2301.  
  2302.  
  2303. ERRDOS = { 1: 'Invalid function',
  2304.            2: 'File not found',
  2305.            3: 'Invalid directory',
  2306.            4: 'Too many open files',
  2307.            5: 'Access denied',
  2308.            6: 'Invalid file handle. Please file a bug report.',
  2309.            7: 'Memory control blocks destroyed',
  2310.            8: 'Out of memory',
  2311.            9: 'Invalid memory block address',
  2312.            10: 'Invalid environment',
  2313.            11: 'Invalid format',
  2314.            12: 'Invalid open mode',
  2315.            13: 'Invalid data',
  2316.            15: 'Invalid drive',
  2317.            16: 'Attempt to remove server\'s current directory',
  2318.            17: 'Not the same device',
  2319.            18: 'No files found',
  2320.            32: 'Sharing mode conflicts detected',
  2321.            33: 'Lock request conflicts detected',
  2322.            80: 'File already exists'
  2323.            }
  2324.  
  2325. ERRSRV = { 1: 'Non-specific error',
  2326.            2: 'Bad password',
  2327.            4: 'Access denied',
  2328.            5: 'Invalid tid. Please file a bug report.',
  2329.            6: 'Invalid network name',
  2330.            7: 'Invalid device',
  2331.            49: 'Print queue full',
  2332.            50: 'Print queue full',
  2333.            51: 'EOF on print queue dump',
  2334.            52: 'Invalid print file handle',
  2335.            64: 'Command not recognized. Please file a bug report.',
  2336.            65: 'Internal server error',
  2337.            67: 'Invalid path',
  2338.            69: 'Invalid access permissions',
  2339.            71: 'Invalid attribute mode',
  2340.            81: 'Server is paused',
  2341.            82: 'Not receiving messages',
  2342.            83: 'No room to buffer messages',
  2343.            87: 'Too many remote user names',
  2344.            88: 'Operation timeout',
  2345.            89: 'Out of resources',
  2346.            91: 'Invalid user handle. Please file a bug report.',
  2347.            250: 'Temporarily unable to support raw mode for transfer',
  2348.            251: 'Temporarily unable to support raw mode for transfer',
  2349.            252: 'Continue in MPX mode',
  2350.            65535: 'Unsupported function'
  2351.            }
  2352.  
  2353. ERRHRD = { 19: 'Media is write-protected',
  2354.            20: 'Unknown unit',
  2355.            21: 'Drive not ready',
  2356.            22: 'Unknown command',
  2357.            23: 'CRC error',
  2358.            24: 'Bad request',
  2359.            25: 'Seek error',
  2360.            26: 'Unknown media type',
  2361.            27: 'Sector not found',
  2362.            28: 'Printer out of paper',
  2363.            29: 'Write fault',
  2364.            30: 'Read fault',
  2365.            31: 'General failure',
  2366.            32: 'Open conflicts with an existing open',
  2367.            33: 'Invalid lock request',
  2368.            34: 'Wrong disk in drive',
  2369.            35: 'FCBs not available',
  2370.            36: 'Sharing buffer exceeded'
  2371.            }
  2372.  
  2373.